|
| 1 | +(** |
| 2 | +--- |
| 3 | +title: UpSet plots |
| 4 | +category: Set comparison charts |
| 5 | +categoryindex: 14 |
| 6 | +index: 2 |
| 7 | +--- |
| 8 | +*) |
| 9 | + |
| 10 | +(*** hide ***) |
| 11 | + |
| 12 | +(*** condition: prepare ***) |
| 13 | +#r "nuget: Newtonsoft.JSON, 13.0.3" |
| 14 | +#r "nuget: DynamicObj, 8.0.0" |
| 15 | +#r "nuget: Giraffe.ViewEngine, 1.4.0" |
| 16 | +#r "../../src/Plotly.NET/bin/Release/netstandard2.0/Plotly.NET.dll" |
| 17 | + |
| 18 | +Plotly.NET.Defaults.DefaultDisplayOptions <- |
| 19 | + Plotly.NET.DisplayOptions.init (PlotlyJSReference = Plotly.NET.PlotlyJSReference.NoReference) |
| 20 | + |
| 21 | +(** |
| 22 | +# UpSet plots |
| 23 | +
|
| 24 | +`Chart.UpSet` compares membership across several sets using a dot matrix and bar charts. |
| 25 | +It is useful when a [Venn diagram](venn.html) would become difficult to read. |
| 26 | +
|
| 27 | +Each matrix column represents an **exclusive intersection**: a member belongs to every set marked |
| 28 | +with a dark dot and to none of the sets marked with a pale dot. Connecting lines join the dark dots. |
| 29 | +The bar above a column counts its members; the horizontal bars on the left show the full set sizes. |
| 30 | +Intersections are ordered by decreasing size by default. |
| 31 | +
|
| 32 | +## Basic example |
| 33 | +
|
| 34 | +Provide one unique label for each set, in the same order as the `sets` input. Members are strings, |
| 35 | +and duplicate entries within a set are ignored. Here, A and B share `"2"` and `"3"` exclusively; |
| 36 | +`"1"` belongs to all three sets and is counted in a separate column. |
| 37 | +
|
| 38 | +The default `MinIntersectionSize` is **5**. This small example uses **1** to show every nonempty |
| 39 | +intersection, including those containing just one member. |
| 40 | +*) |
| 41 | + |
| 42 | +open Plotly.NET |
| 43 | + |
| 44 | +let labels = [| "A"; "B"; "C" |] |
| 45 | + |
| 46 | +let sets = |
| 47 | + [| |
| 48 | + [| "1"; "2"; "3"; "4"; "5"; "6"; "11" |] |
| 49 | + [| "1"; "2"; "3"; "7"; "8"; "9"; "10"; "12"; "13" |] |
| 50 | + [| "1"; "4"; "5"; "6"; "7"; "8"; "9"; "10"; "14"; "15"; "16" |] |
| 51 | + |] |
| 52 | + |
| 53 | +let upset = |
| 54 | + Chart.UpSet( |
| 55 | + labels = labels, |
| 56 | + sets = sets, |
| 57 | + MinIntersectionSize = 1 |
| 58 | + ) |
| 59 | + |> Chart.withTitle "Membership across three sets" |
| 60 | + |> Chart.withSize(640, 500) |
| 61 | + |> Chart.withMarginSize(Left = 65, Right = 25, Top = 65, Bottom = 45) |
| 62 | + |
| 63 | +(*** hide ***) |
| 64 | +upset |> GenericChart.toChartHTML |
| 65 | +(*** include-it-raw ***) |
| 66 | + |
| 67 | +(** |
| 68 | +## Filtering and styling |
| 69 | +
|
| 70 | +Raise `MinIntersectionSize` to hide small intersections. The set-size bars still count all members |
| 71 | +of each input set, including members whose intersection columns have been filtered out. |
| 72 | +
|
| 73 | +`MainColor` controls the bars and the active membership dots and lines. `SecondaryColor` controls |
| 74 | +the inactive dots. `MarkerSize`, `TextFont`, and `TextFontLabel` adjust the matrix markers, |
| 75 | +axis titles, and set labels respectively. |
| 76 | +*) |
| 77 | + |
| 78 | +let upsetStyled = |
| 79 | + Chart.UpSet( |
| 80 | + labels = labels, |
| 81 | + sets = sets, |
| 82 | + MinIntersectionSize = 2, |
| 83 | + MainColor = Color.fromHex "#2A6F97", |
| 84 | + SecondaryColor = Color.fromHex "#DCE6ED", |
| 85 | + MarkerSize = 18, |
| 86 | + TextFont = Font.init(Family = StyleParam.FontFamily.Arial, Size = 14.), |
| 87 | + TextFontLabel = Font.init(Family = StyleParam.FontFamily.Arial, Size = 16.) |
| 88 | + ) |
| 89 | + |> Chart.withTitle "Intersections with at least two members" |
| 90 | + |> Chart.withSize(640, 500) |
| 91 | + |> Chart.withMarginSize(Left = 65, Right = 25, Top = 65, Bottom = 45) |
| 92 | + |
| 93 | +(*** hide ***) |
| 94 | +upsetStyled |> GenericChart.toChartHTML |
| 95 | +(*** include-it-raw ***) |
| 96 | + |
| 97 | +(** |
| 98 | +## Adding member measurements |
| 99 | +
|
| 100 | +`SetData` adds feature plots above the intersection counts. Each map associates a member identifier |
| 101 | +with a measurement and must contain every member in every displayed intersection. A map covering |
| 102 | +only one input set is insufficient; this example builds one map for the entire union. |
| 103 | +
|
| 104 | +Provide one `(chart function, title)` pair in `SetDataChartsTitle` for each map in `SetData`, in the |
| 105 | +same order. The chart function receives the values for one exclusive intersection at a time. |
| 106 | +Here, a box plot shows the measurements for each displayed intersection. For this illustration, |
| 107 | +a member's score is simply the numeric value of its identifier. |
| 108 | +*) |
| 109 | + |
| 110 | +let memberScores = |
| 111 | + sets |
| 112 | + |> Seq.collect id |
| 113 | + |> Seq.distinct |
| 114 | + |> Seq.map (fun memberId -> memberId, float (int memberId)) |
| 115 | + |> Map.ofSeq |
| 116 | + |
| 117 | +let scoreBoxPlot (scores: float[]) = |
| 118 | + Chart.BoxPlot( |
| 119 | + Y = scores, |
| 120 | + BoxPoints = StyleParam.BoxPoints.All, |
| 121 | + Jitter = 0.15, |
| 122 | + PointPos = 0., |
| 123 | + MarkerColor = Color.fromHex "#2A6F97", |
| 124 | + OutlineColor = Color.fromHex "#2A6F97" |
| 125 | + ) |
| 126 | + |
| 127 | +let upsetWithScores = |
| 128 | + Chart.UpSet( |
| 129 | + labels = labels, |
| 130 | + sets = sets, |
| 131 | + MinIntersectionSize = 2, |
| 132 | + SetData = [ memberScores ], |
| 133 | + SetDataChartsTitle = [ (scoreBoxPlot, "Member score") ], |
| 134 | + MarkerSize = 18, |
| 135 | + TextFont = Font.init(Family = StyleParam.FontFamily.Arial, Size = 14.), |
| 136 | + TextFontLabel = Font.init(Family = StyleParam.FontFamily.Arial, Size = 16.) |
| 137 | + ) |
| 138 | + |> Chart.withTitle "Member scores within each intersection" |
| 139 | + |> Chart.withSize(640, 600) |
| 140 | + |> Chart.withMarginSize(Left = 65, Right = 25, Top = 65, Bottom = 45) |
| 141 | + |
| 142 | +(*** hide ***) |
| 143 | +upsetWithScores |> GenericChart.toChartHTML |
| 144 | +(*** include-it-raw ***) |
0 commit comments