@@ -12,9 +12,10 @@ def _project_latlon_to_wgs84(lat, lon):
1212 Projects lat and lon to WGS84 to get regular hexagons on a mapbox map
1313 """
1414 x = lon * np .pi / 180
15- y = np .arctanh (np .sin (lat * np .pi / 180 ))
15+ y = np .arctanh (np .sin (lat * np .pi / 180 ))
1616 return x , y
1717
18+
1819def _project_wgs84_to_latlon (x , y ):
1920 """
2021 Projects lat and lon to WGS84 to get regular hexagons on a mapbox map
@@ -23,6 +24,7 @@ def _project_wgs84_to_latlon(x, y):
2324 lat = (2 * np .arctan (np .exp (y )) - np .pi / 2 ) * 180 / np .pi
2425 return lat , lon
2526
27+
2628def _human_format (number ):
2729 """
2830 Transforms high numbers to human readable numer string
@@ -32,14 +34,17 @@ def _human_format(number):
3234 magnitude = int (np .floor (np .log (number , k )))
3335 return "%.2f%s" % (number / k ** magnitude , units [magnitude ])
3436
37+
3538def _getBoundsZoomLevel (lon_min , lon_max , lat_min , lat_max , mapDim ):
3639 """
3740 Get the mapbox zoom level given bounds and a figure dimension
3841 Source: https://stackoverflow.com/questions/6048975/google-maps-v3-how-to-calculate-the-zoom-level-for-a-given-bounds
3942 """
4043
41- scale = 2 # adjustment to reflect MapBox base tiles are 512x512 vs. Google's 256x256
42- WORLD_DIM = {'height' : 256 * scale , 'width' : 256 * scale }
44+ scale = (
45+ 2 # adjustment to reflect MapBox base tiles are 512x512 vs. Google's 256x256
46+ )
47+ WORLD_DIM = {"height" : 256 * scale , "width" : 256 * scale }
4348 ZOOM_MAX = 18
4449
4550 def latRad (lat ):
@@ -55,11 +60,12 @@ def zoom(mapPx, worldPx, fraction):
5560 lngDiff = lon_max - lon_min
5661 lngFraction = ((lngDiff + 360 ) if lngDiff < 0 else lngDiff ) / 360
5762
58- latZoom = zoom (mapDim [' height' ], WORLD_DIM [' height' ], latFraction )
59- lngZoom = zoom (mapDim [' width' ], WORLD_DIM [' width' ], lngFraction )
63+ latZoom = zoom (mapDim [" height" ], WORLD_DIM [" height" ], latFraction )
64+ lngZoom = zoom (mapDim [" width" ], WORLD_DIM [" width" ], lngFraction )
6065
6166 return min (latZoom , lngZoom , ZOOM_MAX )
6267
68+
6369def _compute_hexbin (
6470 lat = None ,
6571 lon = None ,
@@ -68,7 +74,7 @@ def _compute_hexbin(
6874 color = None ,
6975 nx = None ,
7076 agg_func = None ,
71- min_count = None
77+ min_count = None ,
7278):
7379 """
7480 Computes the aggregation at hexagonal bin level.
@@ -135,7 +141,7 @@ def _compute_hexbin(
135141
136142 d1 = (x - ix1 ) ** 2 + 3.0 * (y - iy1 ) ** 2
137143 d2 = (x - ix2 - 0.5 ) ** 2 + 3.0 * (y - iy2 - 0.5 ) ** 2
138- bdist = ( d1 < d2 )
144+ bdist = d1 < d2
139145
140146 if color is None :
141147 lattice1 = np .zeros ((nx1 , ny1 ))
@@ -186,32 +192,33 @@ def _compute_hexbin(
186192 else :
187193 lattice2 [i , j ] = np .nan
188194
189- accum = np .hstack ((lattice1 .astype (float ).ravel (),
190- lattice2 .astype (float ).ravel ()))
195+ accum = np .hstack (
196+ (lattice1 .astype (float ).ravel (), lattice2 .astype (float ).ravel ())
197+ )
191198 good_idxs = ~ np .isnan (accum )
192-
199+
193200 agreggated_value = accum [good_idxs ]
194201
195202 centers = np .zeros ((n , 2 ), float )
196- centers [:nx1 * ny1 , 0 ] = np .repeat (np .arange (nx1 ), ny1 )
197- centers [:nx1 * ny1 , 1 ] = np .tile (np .arange (ny1 ), nx1 )
198- centers [nx1 * ny1 :, 0 ] = np .repeat (np .arange (nx2 ) + 0.5 , ny2 )
199- centers [nx1 * ny1 :, 1 ] = np .tile (np .arange (ny2 ), nx2 ) + 0.5
203+ centers [: nx1 * ny1 , 0 ] = np .repeat (np .arange (nx1 ), ny1 )
204+ centers [: nx1 * ny1 , 1 ] = np .tile (np .arange (ny1 ), nx1 )
205+ centers [nx1 * ny1 :, 0 ] = np .repeat (np .arange (nx2 ) + 0.5 , ny2 )
206+ centers [nx1 * ny1 :, 1 ] = np .tile (np .arange (ny2 ), nx2 ) + 0.5
200207 centers [:, 0 ] *= dx
201208 centers [:, 1 ] *= dy
202209 centers [:, 0 ] += xmin
203210 centers [:, 1 ] += ymin
204211 centers = centers [good_idxs ]
205212
206213 # Define normalised regular hexagon coordinates
207- hx = [0 , .5 , .5 , 0 , - .5 , - .5 ]
214+ hx = [0 , 0 .5 , 0 .5 , 0 , - 0 .5 , - 0 .5 ]
208215 hy = [
209216 - 0.5 / np .cos (np .pi / 6 ),
210217 - 0.5 * np .tan (np .pi / 6 ),
211218 0.5 * np .tan (np .pi / 6 ),
212219 0.5 / np .cos (np .pi / 6 ),
213220 0.5 * np .tan (np .pi / 6 ),
214- - 0.5 * np .tan (np .pi / 6 )
221+ - 0.5 * np .tan (np .pi / 6 ),
215222 ]
216223
217224 # Number of hexagons needed
@@ -221,7 +228,7 @@ def _compute_hexbin(
221228 dxh = sorted (list (set (np .diff (sorted (centers [:, 0 ])))))[1 ]
222229 dyh = sorted (list (set (np .diff (sorted (centers [:, 1 ])))))[1 ]
223230 nx = dxh * 2
224- ny = 2 / 3 * dyh / (0.5 / np .cos (np .pi / 6 ))
231+ ny = 2 / 3 * dyh / (0.5 / np .cos (np .pi / 6 ))
225232
226233 # Coordinates for all hexagonal patches
227234 hxs = np .array ([hx ] * m ) * nx + np .vstack (centers [:, 0 ])
@@ -236,6 +243,7 @@ def _compute_hexbin(
236243
237244 return hexagons_lats , hexagons_lons , hexagons_ids , agreggated_value
238245
246+
239247def _hexagons_to_geojson (hexagons_lats , hexagons_lons , ids = None ):
240248 """
241249 Creates a geojson of hexagonal features based on the outputs of
@@ -249,12 +257,13 @@ def _hexagons_to_geojson(hexagons_lats, hexagons_lons, ids=None):
249257 points .append (points [0 ])
250258 features .append (
251259 dict (
252- type = ' Feature' ,
260+ type = " Feature" ,
253261 id = idx ,
254- geometry = dict (type = ' Polygon' , coordinates = [points ])
262+ geometry = dict (type = " Polygon" , coordinates = [points ]),
255263 )
256264 )
257- return dict (type = 'FeatureCollection' , features = features )
265+ return dict (type = "FeatureCollection" , features = features )
266+
258267
259268def hexbin_mapbox (
260269 data_frame = None ,
@@ -280,10 +289,10 @@ def hexbin_mapbox(
280289 height = None ,
281290):
282291 args = build_dataframe (args = locals (), constructor = None )
283-
292+
284293 if agg_func is None :
285294 agg_func = np .mean
286-
295+
287296 lat_range = args ["data_frame" ][args ["lat" ]].agg (["min" , "max" ]).values
288297 lon_range = args ["data_frame" ][args ["lon" ]].agg (["min" , "max" ]).values
289298
@@ -310,9 +319,9 @@ def hexbin_mapbox(
310319 else :
311320 mapDim = dict (height = height , width = width )
312321 zoom = _getBoundsZoomLevel (* lon_range , * lat_range , mapDim )
313-
322+
314323 if center is None :
315- center = dict (lat = lat_range .mean (), lon = lon_range .mean ())
324+ center = dict (lat = lat_range .mean (), lon = lon_range .mean ())
316325
317326 if args ["animation_frame" ] is not None :
318327 groups = args ["data_frame" ].groupby (args ["animation_frame" ]).groups
@@ -334,31 +343,27 @@ def hexbin_mapbox(
334343 )
335344 agg_data_frame_list .append (
336345 pd .DataFrame (
337- np .c_ [hexagons_ids , aggregated_value ],
338- columns = ["locations" , "color" ]
346+ np .c_ [hexagons_ids , aggregated_value ], columns = ["locations" , "color" ]
339347 )
340348 )
341- agg_data_frame = pd .concat (
342- agg_data_frame_list , axis = 0 , keys = groups .keys ()
343- ).rename_axis (index = ("frame" , "index" )).reset_index ("frame" )
344-
349+ agg_data_frame = (
350+ pd .concat (agg_data_frame_list , axis = 0 , keys = groups .keys ())
351+ .rename_axis (index = ("frame" , "index" ))
352+ .reset_index ("frame" )
353+ )
354+
345355 agg_data_frame ["color" ] = pd .to_numeric (agg_data_frame ["color" ])
346356
347357 if range_color is None :
348- range_color = [
349- agg_data_frame ["color" ].min (),
350- agg_data_frame ["color" ].max ()
351- ]
358+ range_color = [agg_data_frame ["color" ].min (), agg_data_frame ["color" ].max ()]
352359
353360 return choropleth_mapbox (
354361 data_frame = agg_data_frame ,
355362 geojson = geojson ,
356363 locations = "locations" ,
357364 color = "color" ,
358365 hover_data = {"color" : True , "locations" : False , "frame" : False },
359- animation_frame = (
360- "frame" if args ["animation_frame" ] is not None else None
361- ),
366+ animation_frame = ("frame" if args ["animation_frame" ] is not None else None ),
362367 color_discrete_sequence = color_discrete_sequence ,
363368 color_discrete_map = color_discrete_map ,
364369 labels = labels ,
@@ -375,4 +380,5 @@ def hexbin_mapbox(
375380 height = height ,
376381 )
377382
383+
378384hexbin_mapbox .__doc__ = make_docstring (hexbin_mapbox )
0 commit comments