Skip to content

Commit a68db7d

Browse files
committed
#86: Add functionality and docs for using GeoJSON with geo charts.
1 parent 15ea8d4 commit a68db7d

File tree

5 files changed

+268
-57
lines changed

5 files changed

+268
-57
lines changed

Diff for: docs/5_0_choropleth-map.fsx

+120
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,124 @@ choroplethMap2
131131

132132
(***hide***)
133133
choroplethMap2 |> GenericChart.toChartHTML
134+
(***include-it-raw***)
135+
136+
(**
137+
## Using GeoJSON
138+
139+
[GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) is an open standard format designed for representing simple geographical features, along with their non-spatial attributes.
140+
141+
GeoJSON, or at least the type of GeoJSON accepted by plotly.js are `FeatureCollection`s. A feature has for example the `geometry` field, which defines e.g. the corrdinates of it (think for example the coordinates of a polygon on the map)
142+
and the `properties` field, a key-value pair of properties of the feature.
143+
144+
If you want to use GeoJSON with Plotly.NET (or any plotly flavor really), you have to know the property of the feature you are mapping your data to. In the following example this is simply the `id` of a feature, but you can access any property by `property.key`.
145+
146+
Consider the following GeoJSON:
147+
148+
*)
149+
150+
// we are using the awesome FSharp.Data project here to perform a http request
151+
#r "nuget: FSharp.Data"
152+
153+
open FSharp.Data
154+
open Newtonsoft.Json
155+
156+
let geoJson =
157+
Http.RequestString "https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json"
158+
|> JsonConvert.DeserializeObject // the easiest way to use the GeoJSON object is deserializing the JSON string.
159+
160+
(**
161+
it looks like this:
162+
163+
```JSON
164+
{
165+
"type": "FeatureCollection",
166+
"features": [{
167+
"type": "Feature",
168+
"properties": {
169+
"GEO_ID": "0500000US01001",
170+
"STATE": "01",
171+
"COUNTY": "001",
172+
"NAME": "Autauga",
173+
"LSAD": "County",
174+
"CENSUSAREA": 594.436
175+
},
176+
"geometry": {
177+
"type": "Polygon",
178+
"coordinates": [[[-86.496774, 32.344437], [-86.717897, 32.402814], [-86.814912, 32.340803], [-86.890581, 32.502974], [-86.917595, 32.664169], [-86.71339, 32.661732], [-86.714219, 32.705694], [-86.413116, 32.707386], [-86.411172, 32.409937], [-86.496774, 32.344437]]]
179+
},
180+
"id": "01001"
181+
}, ... MANY more features.
182+
```
183+
184+
It basically contains all US counties as polygons on the map. Note that the `id` property corresponds to the [**fips code**](https://en.wikipedia.org/wiki/FIPS_county_code).
185+
186+
To visualize some data using these counties as locations on a choropleth map, we need some exmaple data:
187+
*)
188+
189+
// we use the awesome Deedle data frame library to parse and extract our location and z data
190+
#r "nuget: Deedle"
191+
open Deedle
192+
open System.IO
193+
open System.Text
194+
195+
let data =
196+
let dataString = Http.RequestString "https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv"
197+
let byteArray = Encoding.UTF8.GetBytes(dataString)
198+
use stream = new MemoryStream(byteArray)
199+
Frame.ReadCsv(stream,true,separators=",",schema="fips=string,unemp=float")
200+
201+
202+
(**
203+
The data looks like this:
204+
*)
205+
206+
207+
data.Print()
208+
209+
(*** include-output ***)
210+
211+
(**
212+
As the data contains the fips code and associated unemployment data, we can use the fips codes as locations and the unemployment as z data:
213+
*)
214+
215+
let locationsGeoJSON: string [] =
216+
data
217+
|> Frame.getCol "fips"
218+
|> Series.values
219+
|> Array.ofSeq
220+
221+
let zGeoJSON: int [] =
222+
data
223+
|> Frame.getCol "unemp"
224+
|> Series.values
225+
|> Array.ofSeq
226+
227+
228+
(**
229+
And finally put together the chart using GeoJSON:
230+
*)
231+
232+
let choroplethGeoJSON =
233+
Chart.ChoroplethMap(
234+
locations = locationsGeoJSON,
235+
z = zGeoJSON,
236+
Locationmode=StyleParam.LocationFormat.GeoJson_Id,
237+
GeoJson = geoJson,
238+
FeatureIdKey="id"
239+
)
240+
|> Chart.withMap(
241+
Geo.init(
242+
Scope=StyleParam.GeoScope.Usa
243+
)
244+
)
245+
|> Chart.withSize (800.,800.)
246+
247+
(*** condition: ipynb ***)
248+
#if IPYNB
249+
choroplethGeoJSON
250+
#endif // IPYNB
251+
252+
(***hide***)
253+
choroplethGeoJSON |> GenericChart.toChartHTML
134254
(***include-it-raw***)

Diff for: src/Plotly.NET/Chart.fs

+74-56
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,6 @@ type Chart =
616616
Chart.Range(x, y, upper, lower, ?Name=Name,?ShowMarkers=ShowMarkers,?Showlegend=Showlegend,?Color=Color,?RangeColor=RangeColor,?Labels=Labels,?TextPosition=TextPosition,?TextFont=TextFont)
617617

618618

619-
620619
/// Displays a range of data by plotting two Y values per data point, with each Y value being drawn as a line
621620
static member Range(x, y, upper, lower,mode,
622621
[<Optional;DefaultParameterValue(null)>] ?Name,
@@ -1463,11 +1462,13 @@ type Chart =
14631462
[<Optional;DefaultParameterValue(null)>] ?Colorscale,
14641463
[<Optional;DefaultParameterValue(null)>] ?Colorbar,
14651464
[<Optional;DefaultParameterValue(null)>] ?Marker,
1465+
[<Optional;DefaultParameterValue(null)>] ?GeoJson,
1466+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string,
14661467
[<Optional;DefaultParameterValue(null)>] ?Zmin,
14671468
[<Optional;DefaultParameterValue(null)>] ?Zmax) =
14681469
Trace.initChoroplethMap (
14691470
TraceStyle.ChoroplethMap (Locations=locations,Z=z,?Text=Text,?Locationmode=Locationmode,?Autocolorscale=Autocolorscale,
1470-
?Colorscale=Colorscale,?Colorbar=Colorbar,?Marker=Marker,?Zmin=Zmin,?Zmax=Zmax)
1471+
?Colorscale=Colorscale,?Colorbar=Colorbar,?Marker=Marker,?Zmin=Zmin,?Zmax=Zmax,?GeoJson=GeoJson,?FeatureIdKey=FeatureIdKey)
14711472
)
14721473
|> GenericChart.ofTraceObject
14731474

@@ -2223,20 +2224,22 @@ type Chart =
22232224
[<Optional;DefaultParameterValue(null)>] ?Dash ,
22242225
[<Optional;DefaultParameterValue(null)>] ?Width : float ,
22252226
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2227+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
22262228
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
22272229
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
22282230
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
22292231
) =
22302232

22312233
Trace.initScatterGeo(
22322234
TraceStyle.ScatterGeo(
2233-
mode = mode ,
2234-
Longitudes = longitudes ,
2235-
Latitudes = latitudes ,
2236-
?GeoJson = GeoJson ,
2237-
?Connectgaps= Connectgaps ,
2238-
?Fill = Fill ,
2239-
?Fillcolor = Fillcolor
2235+
mode = mode ,
2236+
Longitudes = longitudes ,
2237+
Latitudes = latitudes ,
2238+
?GeoJson = GeoJson ,
2239+
?FeatureIdKey = FeatureIdKey ,
2240+
?Connectgaps = Connectgaps ,
2241+
?Fill = Fill ,
2242+
?Fillcolor = Fillcolor
22402243
)
22412244
)
22422245
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2294,6 +2297,7 @@ type Chart =
22942297
[<Optional;DefaultParameterValue(null)>] ?Dash ,
22952298
[<Optional;DefaultParameterValue(null)>] ?Width : float ,
22962299
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2300+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
22972301
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
22982302
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
22992303
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2302,13 +2306,14 @@ type Chart =
23022306

23032307
Trace.initScatterGeo(
23042308
TraceStyle.ScatterGeo(
2305-
mode = mode ,
2306-
Longitudes = longitudes ,
2307-
Latitudes = latitudes ,
2308-
?GeoJson = GeoJson ,
2309-
?Connectgaps= Connectgaps ,
2310-
?Fill = Fill ,
2311-
?Fillcolor = Fillcolor
2309+
mode = mode ,
2310+
Longitudes = longitudes ,
2311+
Latitudes = latitudes ,
2312+
?GeoJson = GeoJson ,
2313+
?FeatureIdKey = FeatureIdKey ,
2314+
?Connectgaps = Connectgaps ,
2315+
?Fill = Fill ,
2316+
?Fillcolor = Fillcolor
23122317
)
23132318
)
23142319
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2365,19 +2370,21 @@ type Chart =
23652370
[<Optional;DefaultParameterValue(null)>] ?Dash ,
23662371
[<Optional;DefaultParameterValue(null)>] ?Width : float ,
23672372
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2373+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
23682374
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
23692375
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
23702376
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
23712377
) =
23722378

23732379
Trace.initScatterGeo(
23742380
TraceStyle.ScatterGeo(
2375-
mode = mode ,
2376-
?Locations = locations ,
2377-
?GeoJson = GeoJson ,
2378-
?Connectgaps= Connectgaps ,
2379-
?Fill = Fill ,
2380-
?Fillcolor = Fillcolor
2381+
mode = mode ,
2382+
?Locations = locations ,
2383+
?GeoJson = GeoJson ,
2384+
?FeatureIdKey = FeatureIdKey ,
2385+
?Connectgaps = Connectgaps ,
2386+
?Fill = Fill ,
2387+
?Fillcolor = Fillcolor
23812388
)
23822389
)
23832390
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2427,6 +2434,7 @@ type Chart =
24272434
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
24282435
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
24292436
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2437+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
24302438
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
24312439
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
24322440
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2436,13 +2444,14 @@ type Chart =
24362444

24372445
Trace.initScatterGeo(
24382446
TraceStyle.ScatterGeo(
2439-
mode = changeMode StyleParam.Mode.Markers ,
2440-
Longitudes = longitudes ,
2441-
Latitudes = latitudes ,
2442-
?GeoJson = GeoJson ,
2443-
?Connectgaps= Connectgaps ,
2444-
?Fill = Fill ,
2445-
?Fillcolor = Fillcolor
2447+
mode = changeMode StyleParam.Mode.Markers ,
2448+
Longitudes = longitudes ,
2449+
Latitudes = latitudes ,
2450+
?GeoJson = GeoJson ,
2451+
?FeatureIdKey = FeatureIdKey ,
2452+
?Connectgaps = Connectgaps ,
2453+
?Fill = Fill ,
2454+
?Fillcolor = Fillcolor
24462455
)
24472456
)
24482457
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2489,6 +2498,7 @@ type Chart =
24892498
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
24902499
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
24912500
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2501+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
24922502
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
24932503
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
24942504
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2499,13 +2509,14 @@ type Chart =
24992509

25002510
Trace.initScatterGeo(
25012511
TraceStyle.ScatterGeo(
2502-
mode = changeMode StyleParam.Mode.Markers ,
2503-
Longitudes = longitudes ,
2504-
Latitudes = latitudes ,
2505-
?GeoJson = GeoJson ,
2506-
?Connectgaps= Connectgaps ,
2507-
?Fill = Fill ,
2508-
?Fillcolor = Fillcolor
2512+
mode = changeMode StyleParam.Mode.Markers ,
2513+
Longitudes = longitudes ,
2514+
Latitudes = latitudes ,
2515+
?GeoJson = GeoJson ,
2516+
?FeatureIdKey = FeatureIdKey ,
2517+
?Connectgaps = Connectgaps ,
2518+
?Fill = Fill ,
2519+
?Fillcolor = Fillcolor
25092520
)
25102521
)
25112522
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2552,6 +2563,7 @@ type Chart =
25522563
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
25532564
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
25542565
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2566+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
25552567
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
25562568
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
25572569
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2624,6 +2636,7 @@ type Chart =
26242636
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
26252637
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
26262638
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2639+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
26272640
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
26282641
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
26292642
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2639,13 +2652,14 @@ type Chart =
26392652

26402653
Trace.initScatterGeo(
26412654
TraceStyle.ScatterGeo(
2642-
mode = changeMode StyleParam.Mode.Lines,
2643-
Longitudes = longitudes ,
2644-
Latitudes = latitudes ,
2645-
?GeoJson = GeoJson ,
2646-
?Connectgaps= Connectgaps ,
2647-
?Fill = Fill ,
2648-
?Fillcolor = Fillcolor
2655+
mode = changeMode StyleParam.Mode.Lines,
2656+
Longitudes = longitudes ,
2657+
Latitudes = latitudes ,
2658+
?GeoJson = GeoJson ,
2659+
?FeatureIdKey = FeatureIdKey ,
2660+
?Connectgaps = Connectgaps ,
2661+
?Fill = Fill ,
2662+
?Fillcolor = Fillcolor
26492663
)
26502664
)
26512665
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2697,6 +2711,7 @@ type Chart =
26972711
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
26982712
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
26992713
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2714+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
27002715
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
27012716
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
27022717
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2713,13 +2728,14 @@ type Chart =
27132728

27142729
Trace.initScatterGeo(
27152730
TraceStyle.ScatterGeo(
2716-
mode = changeMode StyleParam.Mode.Lines,
2717-
Longitudes = longitudes ,
2718-
Latitudes = latitudes ,
2719-
?GeoJson = GeoJson ,
2720-
?Connectgaps= Connectgaps ,
2721-
?Fill = Fill ,
2722-
?Fillcolor = Fillcolor
2731+
mode = changeMode StyleParam.Mode.Lines,
2732+
Longitudes = longitudes ,
2733+
Latitudes = latitudes ,
2734+
?GeoJson = GeoJson ,
2735+
?FeatureIdKey = FeatureIdKey ,
2736+
?Connectgaps = Connectgaps ,
2737+
?Fill = Fill ,
2738+
?Fillcolor = Fillcolor
27232739
)
27242740
)
27252741
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)
@@ -2771,6 +2787,7 @@ type Chart =
27712787
[<Optional;DefaultParameterValue(null)>] ?TextPosition ,
27722788
[<Optional;DefaultParameterValue(null)>] ?TextFont ,
27732789
[<Optional;DefaultParameterValue(null)>] ?GeoJson ,
2790+
[<Optional;DefaultParameterValue(null)>] ?FeatureIdKey: string ,
27742791
[<Optional;DefaultParameterValue(null)>] ?Connectgaps : bool ,
27752792
[<Optional;DefaultParameterValue(null)>] ?Fill : StyleParam.Fill ,
27762793
[<Optional;DefaultParameterValue(null)>] ?Fillcolor
@@ -2786,12 +2803,13 @@ type Chart =
27862803

27872804
Trace.initScatterGeo(
27882805
TraceStyle.ScatterGeo(
2789-
mode = changeMode StyleParam.Mode.Lines,
2790-
Locations = locations ,
2791-
?GeoJson = GeoJson ,
2792-
?Connectgaps= Connectgaps ,
2793-
?Fill = Fill ,
2794-
?Fillcolor = Fillcolor
2806+
mode = changeMode StyleParam.Mode.Lines,
2807+
Locations = locations ,
2808+
?GeoJson = GeoJson ,
2809+
?FeatureIdKey = FeatureIdKey ,
2810+
?Connectgaps = Connectgaps ,
2811+
?Fill = Fill ,
2812+
?Fillcolor = Fillcolor
27952813
)
27962814
)
27972815
|> TraceStyle.TraceInfo(?Name=Name,?Showlegend=Showlegend,?Opacity=Opacity)

0 commit comments

Comments
 (0)