Reputation: 330
I have 1 folium.Map
with 4 featuregroups, each folium.Featuregroup
has an folium.Choropleth
.
So I want to have linear scale for each featuregroup using the bins
list that I've created, which include the quantile result of the columns T*_depot_0
, 2_depots
, 3_depots
or 4_depots
in my dataset.
At the moment I am able to create an linear color scale using the branca
package and add this to my map. But this results in showing ALL linear scales on the map.
What I am looking for is when I change from depot 1 to depot 2 using the layer control that the linear scale of depot 2 is shown, and scales of depots 1, 3, 4 are not shown.
I've tried adding the my color_map
to the specific Featuregroup or Choropleth using add_to
, add_child
methods, but that didnt work.
So how do add (and show) an linear scale to an specific featuregroup?
def add_depot_markers_featuregroup(depot_amount, featuregroup):
for i in range(len(depots_locations)):
if i > depot_amount:
break
folium.Marker(
[depots_locations[i].y, depots_locations[i].x],
popup="Depot_{0}".format(i+1),
icon=folium.Icon(color='cadetblue', icon='solid fa-bicycle', prefix='fa')).add_to(featuregroup)
result_map = folium.Map(location=lat_long_groningen, zoom_start=11, tiles=None)
layer_depot_1 = folium.FeatureGroup(name="1 depot", overlay=False).add_to(result_map)
layer_depot_2 = folium.FeatureGroup(name="2 depots", overlay=False).add_to(result_map)
layer_depot_3 = folium.FeatureGroup(name="3 depots", overlay=False).add_to(result_map)
layer_depot_4 = folium.FeatureGroup(name="4 depots", overlay=False).add_to(result_map)
fs=[layer_depot_1, layer_depot_2, layer_depot_3, layer_depot_4]
for i in range(len(fs)):
add_depot_markers_featuregroup(i, fs[i])
depot_column_name = ""
if i == 0:
depot_column_name = "T*_depot_{0}".format(i)
else:
depot_column_name = "{0}_depots".format(i+1)
bins = list(results[depot_column_name].quantile([0, 0.25, 0.5, 0.75, 1]))
choropleth = folium.Choropleth(
results,
data=results,
key_on='feature.properties.Postcode',
columns=["Postcode", depot_column_name],
fill_color="YlOrRd",
fill_opacity = 0.8,
line_opacity = 0,
line_weight=1,
bins=bins,
highlight=True,
legend_name = "T* per postalcode area based on depot {0}".format(i+1),
threshold_scale=bins,
name="T* of {0} depot per Postalcode area".format(i+1)).geojson.add_to(fs[i])
highlight_function = lambda x: {
'fillColor': '#ffffff',
'color':'#000000',
'fillOpacity': 0.1,
'weight': 0.1
}
color_map = branca.colormap.LinearColormap(
colors=['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'],
index=bins,
vmin=bins[0],
vmax=bins[-1],
caption='Routelength per postcode area based on {0} depots'.format(i+1)
).add_to(result_map)
folium.GeoJson(data=results,
name="tooltip " + depot_column_name,
tooltip=folium.GeoJsonTooltip(fields=['Postcode', "Deliveries", "Area (km2)", "Number of cyclists", "Beardwood approx", depot_column_name], labels=True, sticky=True),
style_function=lambda feature: {
"color": "black",
"weight": 0.5,
},
highlight_function=highlight_function
).add_to(choropleth)
# add legend: https://stackoverflow.com/questions/52911688/python-folium-choropleth-map-colors-incorrect/52981115#52981115
# min_values = results[["T*_depot_0", "2_depots", "3_depots", "4_depots"]].min()
# max_values = results[["T*_depot_0", "2_depots", "3_depots", "4_depots"]].max()
# color_index = range(round(min_values.min()), round(max_values.max()), 5)
# color_map = branca.colormap.LinearColormap(
# colors=['#ffffd4', '#fed98e', '#fe9929', '#d95f0e', '#993404'],
# index=color_index,
# vmin=min_values.min(),
# vmax=max_values.max(),
# caption='Routelength per postcode area'
# ).add_to(result_map)
folium.TileLayer(overlay=True, show=True, control=False, name="T* openstreet").add_to(result_map)
folium.TileLayer('cartodbdark_matter',overlay=True, show=False, name="T* dark mode").add_to(result_map)
folium.TileLayer('cartodbpositron',overlay=True, show=False, name="T* light mode").add_to(result_map)
folium.LayerControl(collapsed=False).add_to(result_map)
result_map.save("lastmilegroningen.html")
result_map
Upvotes: 1
Views: 3241
Reputation: 11
Managed to find a work around. For some reason Choroplet object desn´t have this kind of issue where you cant really use it in a for loop. The underlying GeoJson and StepColormap objects are reachable choropleth.geojson and choropleth.color_scale
Upvotes: 0
Reputation: 485
I think you need something like this.
Here the basic idea is to bind each colormap
to your FeatureGroup
.
That means you need this part of the linked post:
from branca.element import MacroElement
from jinja2 import Template
class BindColormap(MacroElement):
"""Binds a colormap to a given layer.
Parameters
----------
colormap : branca.colormap.ColorMap
The colormap to bind.
"""
def __init__(self, layer, colormap):
super(BindColormap, self).__init__()
self.layer = layer
self.colormap = colormap
self._template = Template(u"""
{% macro script(this, kwargs) %}
{{this.colormap.get_name()}}.svg[0][0].style.display = 'block';
{{this._parent.get_name()}}.on('overlayadd', function (eventLayer) {
if (eventLayer.layer == {{this.layer.get_name()}}) {
{{this.colormap.get_name()}}.svg[0][0].style.display = 'block';
}});
{{this._parent.get_name()}}.on('overlayremove', function (eventLayer) {
if (eventLayer.layer == {{this.layer.get_name()}}) {
{{this.colormap.get_name()}}.svg[0][0].style.display = 'none';
}});
{% endmacro %}
""") # noqa
and at the end you do not add your colormap
and FeatureGroup
to the map but instead bind them then add them to the map like this:
m.add_child(BindColormap(color_map, i)
Upvotes: 1