def create_map(): df = load_data() latitude = df['latitude'] longitude = df['longitude'] popups = df['comment'] n_rivals = df['n_rivals'] vmax = df['n_rivals'].max() m = folium.Map(location=[55.7522, 37.6156]) marker_cluster = MarkerCluster() marker_cluster.add_to(m) folium.LayerControl().add_to(m) for lat, lon, popup, n_rival in zip(latitude, longitude, popups, n_rivals): if 'Калейдоскоп' in popup: popup = 'burgerking\nг.Москва, Химкинский бульвар, д. 7/23 ТЦ Калейдоскоп, 4 этаж\nКонкурентов: 3' folium.Marker(location=[lat, lon], popup=popup, icon=folium.Icon( color=color_change(n_rival))).add_to(marker_cluster) colormap = StepColormap(['green', 'blue', 'orange', 'red'], vmin=0, vmax=vmax, index=[0, 1, 4, 8, vmax]).scale(0, vmax) today = date.today() colormap.caption = f'Количество конкурентов ({today.strftime("%B, %Y")})' colormap.add_to(m) m.save("Moscow_Map.html")
def test_custom_colormaps(self): step = StepColormap(["green", "yellow", "red"], vmin=0, vmax=100000000) m = self.world.explore("pop_est", cmap=step, tooltip=["name"], legend=True) strings = [ 'fillColor":"#008000ff"', # Green '"fillColor":"#ffff00ff"', # Yellow '"fillColor":"#ff0000ff"', # Red ] out_str = self._fetch_map_string(m) for s in strings: assert s in out_str assert out_str.count("008000ff") == 306 assert out_str.count("ffff00ff") == 187 assert out_str.count("ff0000ff") == 190 # Using custom function colormap def my_color_function(field): """Maps low values to green and high values to red.""" if field > 100000000: return "#ff0000" else: return "#008000" m = self.world.explore("pop_est", cmap=my_color_function, legend=False) strings = [ '"color":"#ff0000","fillColor":"#ff0000"', '"color":"#008000","fillColor":"#008000"', ] for s in strings: assert s in self._fetch_map_string(m) # matplotlib.Colormap cmap = colors.ListedColormap( ["red", "green", "blue", "white", "black"]) m = self.nybb.explore("BoroName", cmap=cmap) strings = [ '"fillColor":"#ff0000"', # Red '"fillColor":"#008000"', # Green '"fillColor":"#0000ff"', # Blue '"fillColor":"#ffffff"', # White '"fillColor":"#000000"', # Black ] out_str = self._fetch_map_string(m) for s in strings: assert s in out_str
def choropleth(self, geo_data, data=None, columns=None, key_on=None, threshold_scale=None, fill_color='blue', fill_opacity=0.6, line_color='black', line_weight=1, line_opacity=1, name=None, legend_name='', topojson=None, reset=False, smooth_factor=None, highlight=None): """ Apply a GeoJSON overlay to the map. Plot a GeoJSON overlay on the base map. There is no requirement to bind data (passing just a GeoJSON plots a single-color overlay), but there is a data binding option to map your columnar data to different feature objects with a color scale. If data is passed as a Pandas DataFrame, the "columns" and "key-on" keywords must be included, the first to indicate which DataFrame columns to use, the second to indicate the layer in the GeoJSON on which to key the data. The 'columns' keyword does not need to be passed for a Pandas series. Colors are generated from color brewer (http://colorbrewer2.org/) sequential palettes on a D3 threshold scale. The scale defaults to the following quantiles: [0, 0.5, 0.75, 0.85, 0.9]. A custom scale can be passed to `threshold_scale` of length <=6, in order to match the color brewer range. TopoJSONs can be passed as "geo_data", but the "topojson" keyword must also be passed with the reference to the topojson objects to convert. See the topojson.feature method in the TopoJSON API reference: https://github.com/topojson/topojson/wiki/API-Reference Parameters ---------- geo_data: string/object URL, file path, or data (json, dict, geopandas, etc) to your GeoJSON geometries data: Pandas DataFrame or Series, default None Data to bind to the GeoJSON. columns: dict or tuple, default None If the data is a Pandas DataFrame, the columns of data to be bound. Must pass column 1 as the key, and column 2 the values. key_on: string, default None Variable in the GeoJSON file to bind the data to. Must always start with 'feature' and be in JavaScript objection notation. Ex: 'feature.id' or 'feature.properties.statename'. threshold_scale: list, default None Data range for D3 threshold scale. Defaults to the following range of quantiles: [0, 0.5, 0.75, 0.85, 0.9], rounded to the nearest order-of-magnitude integer. Ex: 270 rounds to 200, 5600 to 6000. fill_color: string, default 'blue' Area fill color. Can pass a hex code, color name, or if you are binding data, one of the following color brewer palettes: 'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'RdPu', 'YlGn', 'YlGnBu', 'YlOrBr', and 'YlOrRd'. fill_opacity: float, default 0.6 Area fill opacity, range 0-1. line_color: string, default 'black' GeoJSON geopath line color. line_weight: int, default 1 GeoJSON geopath line weight. line_opacity: float, default 1 GeoJSON geopath line opacity, range 0-1. legend_name: string, default empty string Title for data legend. topojson: string, default None If using a TopoJSON, passing "objects.yourfeature" to the topojson keyword argument will enable conversion to GeoJSON. reset: boolean, default False Remove all current geoJSON layers, start with new layer smooth_factor: float, default None How much to simplify the polyline on each zoom level. More means better performance and smoother look, and less means more accurate representation. Leaflet defaults to 1.0. highlight: boolean, default False Enable highlight functionality when hovering over a GeoJSON area. Returns ------- GeoJSON data layer in obj.template_vars Examples -------- >>> m.choropleth(geo_data='us-states.json', line_color='blue', ... line_weight=3) >>> m.choropleth(geo_data='geo.json', data=df, ... columns=['Data 1', 'Data 2'], ... key_on='feature.properties.myvalue', ... fill_color='PuBu', ... threshold_scale=[0, 20, 30, 40, 50, 60]) >>> m.choropleth(geo_data='countries.json', ... topojson='objects.countries') >>> m.choropleth(geo_data='geo.json', data=df, ... columns=['Data 1', 'Data 2'], ... key_on='feature.properties.myvalue', ... fill_color='PuBu', ... threshold_scale=[0, 20, 30, 40, 50, 60], ... highlight=True) """ if threshold_scale and len(threshold_scale) > 6: raise ValueError if data is not None and not color_brewer(fill_color): raise ValueError('Please pass a valid color brewer code to ' 'fill_local. See docstring for valid codes.') # Create color_data dict if hasattr(data, 'set_index'): # This is a pd.DataFrame color_data = data.set_index(columns[0])[columns[1]].to_dict() elif hasattr(data, 'to_dict'): # This is a pd.Series color_data = data.to_dict() elif data: color_data = dict(data) else: color_data = None # Compute color_domain if threshold_scale: color_domain = list(threshold_scale) elif color_data: # To avoid explicit pandas dependency ; changed default behavior. data_min = min(color_data.values()) data_max = max(color_data.values()) if data_min == data_max: data_min = (data_min if data_min < 0 else 0 if data_min > 0 else -1) data_max = (data_max if data_max > 0 else 0 if data_max < 0 else 1) data_min, data_max = (1.01 * data_min - 0.01 * data_max, 1.01 * data_max - 0.01 * data_min) nb_class = 6 color_domain = [ data_min + i * (data_max - data_min) * 1. / nb_class for i in range(1 + nb_class) ] else: color_domain = None if color_domain and key_on: key_on = key_on[8:] if key_on.startswith('feature.') else key_on color_range = color_brewer(fill_color, n=len(color_domain)) def get_by_key(obj, key): return (obj.get(key, None) if len(key.split('.')) <= 1 else get_by_key(obj.get(key.split('.')[0], None), '.'.join( key.split('.')[1:]))) def color_scale_fun(x): return color_range[len([ u for u in color_domain if get_by_key(x, key_on) in color_data and u <= color_data[get_by_key(x, key_on)] ])] else: def color_scale_fun(x): return fill_color def style_function(x): return { 'weight': line_weight, 'opacity': line_opacity, 'color': line_color, 'fillOpacity': fill_opacity, 'fillColor': color_scale_fun(x) } def highlight_function(x): return { 'weight': line_weight + 2, 'fillOpacity': fill_opacity + .2 } if topojson: geo_json = TopoJson(geo_data, topojson, name=name, style_function=style_function, smooth_factor=smooth_factor) else: geo_json = GeoJson( geo_data, name=name, style_function=style_function, smooth_factor=smooth_factor, highlight_function=highlight_function if highlight else None) self.add_child(geo_json) # Create ColorMap. if color_domain: brewed = color_brewer(fill_color, n=len(color_domain)) color_scale = StepColormap( brewed[1:len(color_domain)], index=color_domain, vmin=color_domain[0], vmax=color_domain[-1], caption=legend_name, ) self.add_child(color_scale)
def choropleth(self, geo_data, data=None, columns=None, key_on=None, bins=6, fill_color='blue', nan_fill_color='black', fill_opacity=0.6, nan_fill_opacity=None, line_color='black', line_weight=1, line_opacity=1, name=None, legend_name='', topojson=None, reset=False, smooth_factor=None, highlight=None, **kwargs): """ Apply a GeoJSON overlay to the map. Plot a GeoJSON overlay on the base map. There is no requirement to bind data (passing just a GeoJSON plots a single-color overlay), but there is a data binding option to map your columnar data to different feature objects with a color scale. If data is passed as a Pandas DataFrame, the "columns" and "key-on" keywords must be included, the first to indicate which DataFrame columns to use, the second to indicate the layer in the GeoJSON on which to key the data. The 'columns' keyword does not need to be passed for a Pandas series. Colors are generated from color brewer (http://colorbrewer2.org/) sequential palettes. By default, linear binning is used between the min and the max of the values. Custom binning can be achieved with the `bins` parameter. TopoJSONs can be passed as "geo_data", but the "topojson" keyword must also be passed with the reference to the topojson objects to convert. See the topojson.feature method in the TopoJSON API reference: https://github.com/topojson/topojson/wiki/API-Reference Parameters ---------- geo_data: string/object URL, file path, or data (json, dict, geopandas, etc) to your GeoJSON geometries data: Pandas DataFrame or Series, default None Data to bind to the GeoJSON. columns: dict or tuple, default None If the data is a Pandas DataFrame, the columns of data to be bound. Must pass column 1 as the key, and column 2 the values. key_on: string, default None Variable in the `geo_data` GeoJSON file to bind the data to. Must start with 'feature' and be in JavaScript objection notation. Ex: 'feature.id' or 'feature.properties.statename'. bins: int or sequence of scalars or str, default 6 If `bins` is an int, it defines the number of equal-width bins between the min and the max of the values. If `bins` is a sequence, it directly defines the bin edges. For more information on this parameter, have a look at numpy.histogram function. fill_color: string, default 'blue' Area fill color. Can pass a hex code, color name, or if you are binding data, one of the following color brewer palettes: 'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'RdPu', 'YlGn', 'YlGnBu', 'YlOrBr', and 'YlOrRd'. nan_fill_color: string, default 'black' Area fill color for nan or missing values. Can pass a hex code, color name. fill_opacity: float, default 0.6 Area fill opacity, range 0-1. nan_fill_opacity: float, default fill_opacity Area fill opacity for nan or missing values, range 0-1. line_color: string, default 'black' GeoJSON geopath line color. line_weight: int, default 1 GeoJSON geopath line weight. line_opacity: float, default 1 GeoJSON geopath line opacity, range 0-1. legend_name: string, default empty string Title for data legend. topojson: string, default None If using a TopoJSON, passing "objects.yourfeature" to the topojson keyword argument will enable conversion to GeoJSON. reset: boolean, default False Remove all current geoJSON layers, start with new layer smooth_factor: float, default None How much to simplify the polyline on each zoom level. More means better performance and smoother look, and less means more accurate representation. Leaflet defaults to 1.0. highlight: boolean, default False Enable highlight functionality when hovering over a GeoJSON area. Returns ------- GeoJSON data layer in obj.template_vars Examples -------- >>> m.choropleth(geo_data='us-states.json', line_color='blue', ... line_weight=3) >>> m.choropleth(geo_data='geo.json', data=df, ... columns=['Data 1', 'Data 2'], ... key_on='feature.properties.myvalue', ... fill_color='PuBu', ... bins=[0, 20, 30, 40, 50, 60]) >>> m.choropleth(geo_data='countries.json', ... topojson='objects.countries') >>> m.choropleth(geo_data='geo.json', data=df, ... columns=['Data 1', 'Data 2'], ... key_on='feature.properties.myvalue', ... fill_color='PuBu', ... bins=[0, 20, 30, 40, 50, 60], ... highlight=True) """ if data is not None and not color_brewer(fill_color): raise ValueError('Please pass a valid color brewer code to ' 'fill_local. See docstring for valid codes.') if nan_fill_opacity is None: nan_fill_opacity = fill_opacity if 'threshold_scale' in kwargs: if kwargs['threshold_scale'] is not None: bins = kwargs['threshold_scale'] warnings.warn( 'choropleth `threshold_scale` parameter is now depreciated ' 'in favor of the `bins` parameter.', DeprecationWarning) # Create color_data dict if hasattr(data, 'set_index'): # This is a pd.DataFrame color_data = data.set_index(columns[0])[columns[1]].to_dict() elif hasattr(data, 'to_dict'): # This is a pd.Series color_data = data.to_dict() elif data: color_data = dict(data) else: color_data = None if color_data is not None and key_on is not None: real_values = np.array(list(color_data.values())) real_values = real_values[~np.isnan(real_values)] _, bin_edges = np.histogram(real_values, bins=bins) bins_min, bins_max = min(bin_edges), max(bin_edges) if np.any((real_values < bins_min) | (real_values > bins_max)): raise ValueError( 'All values are expected to fall into one of the provided ' 'bins (or to be Nan). Please check the `bins` parameter ' 'and/or your data.') # We add the colorscale nb_bins = len(bin_edges) - 1 color_range = color_brewer(fill_color, n=nb_bins) color_scale = StepColormap(color_range, index=bin_edges, vmin=bins_min, vmax=bins_max, caption=legend_name) self.add_child(color_scale) # then we 'correct' the last edge for numpy digitize # (we add a very small amount to fake an inclusive right interval) increasing = bin_edges[0] <= bin_edges[-1] bin_edges[-1] = np.nextafter(bin_edges[-1], (1 if increasing else -1) * np.inf) key_on = key_on[8:] if key_on.startswith('feature.') else key_on def get_by_key(obj, key): return (obj.get(key, None) if len(key.split('.')) <= 1 else get_by_key(obj.get(key.split('.')[0], None), '.'.join( key.split('.')[1:]))) def color_scale_fun(x): key_of_x = get_by_key(x, key_on) if key_of_x not in color_data.keys(): return nan_fill_color, nan_fill_opacity value_of_x = color_data[key_of_x] if np.isnan(value_of_x): return nan_fill_color, nan_fill_opacity color_idx = np.digitize(value_of_x, bin_edges, right=False) - 1 return color_range[color_idx], fill_opacity else: def color_scale_fun(x): return fill_color, fill_opacity def style_function(x): color, opacity = color_scale_fun(x) return { 'weight': line_weight, 'opacity': line_opacity, 'color': line_color, 'fillOpacity': opacity, 'fillColor': color } def highlight_function(x): return { 'weight': line_weight + 2, 'fillOpacity': fill_opacity + .2 } if topojson: geo_json = TopoJson(geo_data, topojson, name=name, style_function=style_function, smooth_factor=smooth_factor) else: geo_json = GeoJson( geo_data, name=name, style_function=style_function, smooth_factor=smooth_factor, highlight_function=highlight_function if highlight else None) self.add_child(geo_json)
def choropleth(self, geo_path=None, geo_str=None, data_out='data.json', data=None, columns=None, key_on=None, threshold_scale=None, fill_color='blue', fill_opacity=0.6, line_color='black', line_weight=1, line_opacity=1, legend_name="", topojson=None, popup_function=None, reset=False): """ Apply a GeoJSON overlay to the map. Plot a GeoJSON overlay on the base map. There is no requirement to bind data (passing just a GeoJSON plots a single-color overlay), but there is a data binding option to map your columnar data to different feature objects with a color scale. If data is passed as a Pandas dataframe, the "columns" and "key-on" keywords must be included, the first to indicate which DataFrame columns to use, the second to indicate the layer in the GeoJSON on which to key the data. The 'columns' keyword does not need to be passed for a Pandas series. Colors are generated from color brewer (http://colorbrewer2.org/) sequential palettes on a D3 threshold scale. The scale defaults to the following quantiles: [0, 0.5, 0.75, 0.85, 0.9]. A custom scale can be passed to `threshold_scale` of length <=6, in order to match the color brewer range. TopoJSONs can be passed as "geo_path", but the "topojson" keyword must also be passed with the reference to the topojson objects to convert. See the topojson.feature method in the TopoJSON API reference: https://github.com/mbostock/topojson/wiki/API-Reference Parameters ---------- geo_path: string, default None URL or File path to your GeoJSON data geo_str: string, default None String of GeoJSON, alternative to geo_path data_out: string, default 'data.json' Path to write Pandas DataFrame/Series to JSON if binding data data: Pandas DataFrame or Series, default None Data to bind to the GeoJSON. columns: dict or tuple, default None If the data is a Pandas DataFrame, the columns of data to be bound. Must pass column 1 as the key, and column 2 the values. key_on: string, default None Variable in the GeoJSON file to bind the data to. Must always start with 'feature' and be in JavaScript objection notation. Ex: 'feature.id' or 'feature.properties.statename'. threshold_scale: list, default None Data range for D3 threshold scale. Defaults to the following range of quantiles: [0, 0.5, 0.75, 0.85, 0.9], rounded to the nearest order-of-magnitude integer. Ex: 270 rounds to 200, 5600 to 6000. fill_color: string, default 'blue' Area fill color. Can pass a hex code, color name, or if you are binding data, one of the following color brewer palettes: 'BuGn', 'BuPu', 'GnBu', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'RdPu', 'YlGn', 'YlGnBu', 'YlOrBr', and 'YlOrRd'. fill_opacity: float, default 0.6 Area fill opacity, range 0-1. line_color: string, default 'black' GeoJSON geopath line color. line_weight: int, default 1 GeoJSON geopath line weight. line_opacity: float, default 1 GeoJSON geopath line opacity, range 0-1. legend_name: string, default empty string Title for data legend. topojson: string, default None If using a TopoJSON, passing "objects.yourfeature" to the topojson keyword argument will enable conversion to GeoJSON. popup_function: string or function, default None If using GeoJson a string or function to pass through to the map to create popups based on feature attributes. Ignored for topojson. reset: boolean, default False Remove all current geoJSON layers, start with new layer Returns ------- GeoJSON data layer in obj.template_vars Examples -------- >>> m.choropleth(geo_path='us-states.json', line_color='blue', ... line_weight=3) >>> m.choropleth(geo_path='geo.json', data=df, ... columns=['Data 1', 'Data 2'], ... key_on='feature.properties.myvalue', ... fill_color='PuBu', ... threshold_scale=[0, 20, 30, 40, 50, 60]) >>> m.choropleth(geo_path='countries.json', ... topojson='objects.countries') """ if threshold_scale and len(threshold_scale) > 6: raise ValueError if data is not None and not color_brewer(fill_color): raise ValueError('Please pass a valid color brewer code to ' 'fill_local. See docstring for valid codes.') # Create GeoJson object if geo_path: geo_data = open(geo_path) elif geo_str: geo_data = geo_str else: geo_data = {} # Create color_data dict if hasattr(data, 'set_index'): # This is a pd.DataFrame color_data = data.set_index(columns[0])[columns[1]].to_dict() elif hasattr(data, 'to_dict'): # This is a pd.Series color_data = data.to_dict() elif data: color_data = dict(data) else: color_data = None # Compute color_domain if threshold_scale: color_domain = list(threshold_scale) elif color_data: # To avoid explicit pandas dependency ; changed default behavior. warnings.warn( "'threshold_scale' default behavior has changed." " Now you get a linear scale between the 'min' and" " the 'max' of your data." " To get former behavior, use" " folium.utilities.split_six.", FutureWarning, stacklevel=2) data_min = min(color_data.values()) data_max = max(color_data.values()) if data_min == data_max: data_min = (data_min if data_min < 0 else 0 if data_min > 0 else -1) data_max = (data_max if data_max > 0 else 0 if data_max < 0 else 1) data_min, data_max = (1.01 * data_min - 0.01 * data_max, 1.01 * data_max - 0.01 * data_min) nb_class = 6 color_domain = [ data_min + i * (data_max - data_min) * 1. / nb_class for i in range(1 + nb_class) ] else: color_domain = None if color_domain and key_on: key_on = key_on[8:] if key_on.startswith('feature.') else key_on color_range = color_brewer(fill_color, n=len(color_domain)) def get_by_key(obj, key): return (obj.get(key, None) if len(key.split('.')) <= 1 else get_by_key(obj.get(key.split('.')[0], None), '.'.join( key.split('.')[1:]))) def color_scale_fun(x): return color_range[len([ u for u in color_domain if u <= color_data[get_by_key(x, key_on)] ])] else: def color_scale_fun(x): return fill_color def style_function(x): return { "weight": line_weight, "opactiy": line_opacity, "color": line_color, "fillOpacity": fill_opacity, "fillColor": color_scale_fun(x) } if topojson: geo_json = TopoJson(geo_data, topojson, style_function=style_function) # noqa else: geo_json = GeoJson(geo_data, style_function=style_function, popup_function=popup_function) self.add_children(geo_json) # Create ColorMap. if color_domain: brewed = color_brewer(fill_color, n=len(color_domain)) color_scale = StepColormap( brewed[1:len(color_domain)], index=color_domain, vmin=color_domain[0], vmax=color_domain[-1], ) self.add_children(color_scale)
def __init__(self, geo_data, data=None, columns=None, key_on=None, # noqa bins=6, fill_color='blue', nan_fill_color='black', fill_opacity=0.6, nan_fill_opacity=None, line_color='black', line_weight=1, line_opacity=1, name=None, legend_name='', overlay=True, control=True, show=True, topojson=None, smooth_factor=None, highlight=None, **kwargs): super(Choropleth, self).__init__(name=name, overlay=overlay, control=control, show=show) self._name = 'Choropleth' if data is not None and not color_brewer(fill_color): raise ValueError('Please pass a valid color brewer code to ' 'fill_local. See docstring for valid codes.') if nan_fill_opacity is None: nan_fill_opacity = fill_opacity if 'threshold_scale' in kwargs: if kwargs['threshold_scale'] is not None: bins = kwargs['threshold_scale'] warnings.warn( 'choropleth `threshold_scale` parameter is now depreciated ' 'in favor of the `bins` parameter.', DeprecationWarning) # Create color_data dict if hasattr(data, 'set_index'): # This is a pd.DataFrame color_data = data.set_index(columns[0])[columns[1]].to_dict() elif hasattr(data, 'to_dict'): # This is a pd.Series color_data = data.to_dict() elif data: color_data = dict(data) else: color_data = None self.color_scale = None if color_data is not None and key_on is not None: real_values = np.array(list(color_data.values())) real_values = real_values[~np.isnan(real_values)] _, bin_edges = np.histogram(real_values, bins=bins) bins_min, bins_max = min(bin_edges), max(bin_edges) if np.any((real_values < bins_min) | (real_values > bins_max)): raise ValueError( 'All values are expected to fall into one of the provided ' 'bins (or to be Nan). Please check the `bins` parameter ' 'and/or your data.') # We add the colorscale nb_bins = len(bin_edges) - 1 color_range = color_brewer(fill_color, n=nb_bins) self.color_scale = StepColormap( color_range, index=bin_edges, vmin=bins_min, vmax=bins_max, caption=legend_name) # then we 'correct' the last edge for numpy digitize # (we add a very small amount to fake an inclusive right interval) increasing = bin_edges[0] <= bin_edges[-1] bin_edges[-1] = np.nextafter( bin_edges[-1], (1 if increasing else -1) * np.inf) key_on = key_on[8:] if key_on.startswith('feature.') else key_on def get_by_key(obj, key): return (obj.get(key, None) if len(key.split('.')) <= 1 else get_by_key(obj.get(key.split('.')[0], None), '.'.join(key.split('.')[1:]))) def color_scale_fun(x): key_of_x = get_by_key(x, key_on) if key_of_x not in color_data.keys(): return nan_fill_color, nan_fill_opacity value_of_x = color_data[key_of_x] if np.isnan(value_of_x): return nan_fill_color, nan_fill_opacity color_idx = np.digitize(value_of_x, bin_edges, right=False) - 1 return color_range[color_idx], fill_opacity else: def color_scale_fun(x): return fill_color, fill_opacity def style_function(x): color, opacity = color_scale_fun(x) return { 'weight': line_weight, 'opacity': line_opacity, 'color': line_color, 'fillOpacity': opacity, 'fillColor': color } def highlight_function(x): return { 'weight': line_weight + 2, 'fillOpacity': fill_opacity + .2 } if topojson: self.geojson = TopoJson( geo_data, topojson, style_function=style_function, smooth_factor=smooth_factor) else: self.geojson = GeoJson( geo_data, style_function=style_function, smooth_factor=smooth_factor, highlight_function=highlight_function if highlight else None) self.add_child(self.geojson) if self.color_scale: self.add_child(self.color_scale)