将branca.colormap.LinearColormap添加到folium.FeatureGroup?

问题描述 投票:0回答:2

我有 1 个

folium.Map
,有 4 个功能组,每个
folium.Featuregroup
都有一个
folium.Choropleth

因此,我想使用我创建的

bins
列表为每个特征组设置线性比例,其中包括数据集中的
T*_depot_0
2_depots
3_depots
4_depots
列的分位数结果。

目前,我可以使用

branca
包创建线性色标并将其添加到我的地图中。但这会导致在地图上显示所有线性比例。

我正在寻找的是,当我使用图层控件从仓库1更改为仓库2时,显示仓库2的线性比例,并且不显示仓库1、3、4的比例。

我尝试使用

color_map
add_to
方法将我的
add_child
添加到特定的要素组或 Choropleth,但这不起作用。

那么如何向特定特征组添加(并显示)线性比例?

我的数据(Geopandas 数据框):

我的代码:

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

目前结果

python pandas legend geopandas folium
2个回答
1
投票

我认为你需要类似这个的东西。

这里的基本思想是将每个

colormap
绑定到你的
FeatureGroup
。 这意味着您需要链接帖子的这一部分:

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

最后,您不会将

colormap
FeatureGroup
添加到地图中,而是绑定它们,然后将它们添加到地图中,如下所示:

m.add_child(BindColormap(color_map, i)

0
投票

设法找到解决方法。由于某种原因,Choroplet 对象不存在这种问题,即您无法在 for 循环中真正使用它。底层的 GeoJson 和 StepColormap 对象可访问 choropleth.geojson 和 choropleth.color_scale

© www.soinside.com 2019 - 2024. All rights reserved.