首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于自定义值绘制多边形GeoJson填充颜色

基于自定义值绘制多边形GeoJson填充颜色
EN

Stack Overflow用户
提问于 2021-11-19 05:13:41
回答 1查看 2.2K关注 0票数 0

我拥有与GeoDataFrame中的标识符相关联的lat/long值的多边形,如下所示。考虑一个有两个标识符AB的例子,多边形A有三个点,B有四个点,它们的lat/long值如下所示。对应于每一点(lat/long),我还有一个相关的数值,如最后一列所示。

代码语言:javascript
复制
id    geometry                                                                         values
A   POLYGON((lat_A_1 long_A_1, lat_A_2 long_A_2, lat_A_3 long_A_3))                    10,12,13
B   POLYGON((lat_B_1 long_B_1, lat_B_2 long_B_2, lat_B_3 long_B_3, lat_B_4 long_B_4))  4,8,16,20

我在GeoDataFrame上迭代并使用下面的代码在地图上绘制这些多边形

代码语言:javascript
复制
    geo_j = folium.GeoJson(data=geo_j,
                           style_function={ 
                               'fillColor': 'blue'
                           })

是否有一种方法可以根据values列填充多边形,如红色0-5,蓝色6-10,绿色11-20。这是如何做到的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-25 15:45:03

  • 首先获取一些多边形并定义一个值(生成MWE样本数据集)
  • ,这意味着与多边形相关的值与多边形中的点相同。您使用folium请求一个解决方案,该解决方案使用自定义颜色映射值填充多边形。这意味着您需要一个函数将所有这些值同化为多边形(颜色)的单个值。我使用了模式,这是最常见的值。这可能是平均的,中位数或任何其他function.
  • solution然后变得简单,它是folium.GeoJson()使用和适当结构的style_function
  • extended答案。您可以将多边形拆分为较小的多边形,并将子多边形的颜色与点相关联。view
  • shapley提供了两种拆分多边形https://shapely.readthedocs.io/en/stable/manual.html#shapely.ops.triangulate的方法,folium的生产没有改变(包括iso_a3)。发现沃罗诺伊是更有效的

生成MWE数据

代码语言:javascript
复制
# some polygons
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).loc[lambda d: d["iso_a3"].isin(["BEL", "LUX", "NLD", "DEU", "AUT"]), ["geometry"]]

# comma separated values column... between 0 and 20...
gdf["values"] = gdf.geometry.apply(lambda p: ",".join([str(int(sum(xy)) % 20) for xy in p.exterior.coords]))
# id column
gdf["id"] = list("ABCDEFGHIJ")[0 : len(gdf)]
gdf = gdf.set_index("id", drop=False)

数据

代码语言:javascript
复制
                                   geometry                                   values id
id                                                                                     
A   POLYGON ((16.97967 48.12350, 16.9037...  5,4,4,4,3,2,1,1,0,19,19,18,17,17,16,...  A
B   POLYGON ((14.11969 53.75703, 14.3533...  7,7,7,7,6,6,6,5,5,4,4,3,2,2,2,2,2,1,...  B
C   POLYGON ((6.04307 50.12805, 6.24275 ...                     16,16,15,15,15,15,16  C
D   POLYGON ((6.15666 50.80372, 6.04307 ...  16,16,15,15,14,14,13,13,13,13,14,14,...  D
E   POLYGON ((6.90514 53.48216, 7.09205 ...  0,0,19,18,17,16,16,16,15,14,14,15,17...  E

解决方案

代码语言:javascript
复制
import statistics as st
import branca.colormap
import geopandas as gpd
import folium

m = folium.Map(
    location=[
        sum(gdf.geometry.total_bounds[[1, 3]]) / 2,
        sum(gdf.geometry.total_bounds[[0, 2]]) / 2,
    ],
    zoom_start=5,
    control_scale=True,
)

# style the polygons based on "values" property
def style_fn(feature):
    cm = branca.colormap.LinearColormap(["mistyrose", "tomato", "red"], vmin=0, vmax=20)
    most_common = st.mode([int(v) for v in feature["properties"]["values"].split(",")])
    ss = {
        "fillColor": cm(most_common),
        "fillOpacity": 0.8,
        "weight": 0.8,
        "color": cm(most_common),
    }
    return ss


folium.GeoJson(
    gdf.__geo_interface__,
    style_function=style_fn,
    tooltip=folium.features.GeoJsonTooltip(["id", "values"]),
).add_to(m)

m

将多边形分成几个部分

代码语言:javascript
复制
import statistics as st
import branca.colormap
import geopandas as gpd
import folium
import shapely.geometry
import shapely.ops
import pandas as pd

# some polygons
# fmt: off
gdf = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")).loc[lambda d: d["iso_a3"].isin(["BEL", "LUX", "NLD", "DEU", "AUT","POL"]), ["geometry", "iso_a3"]]

# comma separated values column... between 0 and 20...
gdf["values"] = gdf.geometry.apply(lambda p: ",".join([str(int(sum(xy)) % 20) for xy in p.exterior.coords]))
# id column
gdf["id"] = list("ABCDEFGHIJ")[0 : len(gdf)]
gdf = gdf.set_index("id", drop=False)
# fmt: on


def sub_polygons(r, method="voronoi"):
    g = r["geometry"]
    # split into sub-polygons
    if method == "voronoi":
        geoms = shapely.ops.voronoi_diagram(g).geoms
    elif method == "triangulate":
        geoms = [
            p
            for p in shapely.ops.triangulate(g)
            if isinstance(p.intersection(g), shapely.geometry.Polygon)
        ]
    else:
        raise "invalid polygon ops method"
        
    # clip sub-geometries
    geoms = [p.intersection(g) for p in geoms]
    vs = r["values"].split(",")
    vr = []
    # order or sub-polygons and points are differenct.  use value from point
    # in sub-polygon
    for vg in geoms:
        for i, xy in enumerate(g.exterior.coords):
            if not shapely.geometry.Point(xy).intersection(vg).is_empty:
                break
        vr.append(vs[i])
    return [{**r.to_dict(), **{"geometry": g, "values": v}} for g, v in zip(geoms, vr)]


gdf2 = gpd.GeoDataFrame(
    gdf.apply(sub_polygons, axis=1, method="voronoi").explode().apply(pd.Series)
)


m = folium.Map(
    location=[
        sum(gdf.geometry.total_bounds[[1, 3]]) / 2,
        sum(gdf.geometry.total_bounds[[0, 2]]) / 2,
    ],
    zoom_start=5,
    control_scale=True,
)

# style the polygons based on "values" property
def style_fn(feature):
    cm = branca.colormap.LinearColormap(["mistyrose", "tomato", "red"], vmin=0, vmax=20)
    most_common = st.mode([int(v) for v in feature["properties"]["values"].split(",")])
    ss = {
        "fillColor": cm(most_common),
        "fillOpacity": 0.8,
        "weight": 0.8,
        "color": cm(most_common),
    }
    return ss


folium.GeoJson(
    gdf2.__geo_interface__,
    style_function=style_fn,
    tooltip=folium.features.GeoJsonTooltip(["id", "values", "iso_a3"]),
).add_to(m)

m

用FeatureGroup

代码语言:javascript
复制
m = folium.Map(
    location=[
        sum(gdf.geometry.total_bounds[[1, 3]]) / 2,
        sum(gdf.geometry.total_bounds[[0, 2]]) / 2,
    ],
    zoom_start=5,
    control_scale=True,
)

for g, d in gdf2.groupby(level=0):
    fg = folium.map.FeatureGroup(name=g)
    folium.GeoJson(
        d.__geo_interface__,
        style_function=style_fn,
        tooltip=folium.features.GeoJsonTooltip(["id", "values", "iso_a3"]),
    ).add_to(fg)
    fg.add_to(m)
    
folium.LayerControl().add_to(m)    
m
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70030163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档