来自 Geopandas Dataframe 的 Python Chloropleth Mapbox

Posted

技术标签:

【中文标题】来自 Geopandas Dataframe 的 Python Chloropleth Mapbox【英文标题】:Python Chloropleth Mapbox from Geopandas Dataframe 【发布时间】:2022-01-08 04:02:23 【问题描述】:

我有一个 geopandas 数据框 df,它看起来像这样:

st_astext 列设置为数据框几何。我正在尝试将其绘制为一个 plotly mapbox chloropleth map,其颜色与cnt 中的多边形成比例st_astext,使用

trcs = [px.choropleth_mapbox(df, geojson=df.geometry, locations=df['id'], color='cnt', color_continuous_scale="Viridis")]
lout = go.Layout(title='ch', mapbox_accesstoken=mapToken, width=1600, height=1200, mapbox='style':'streets', 'zoom':10.5,'center':'lat':boundingBox['centroid_lat'].values[0], 'lon':boundingBox['centroid_lon'].values[0])
plyoff.iplot(go.Figure(data=trcs, Layout=lout))

这给了我这个部分堆栈跟踪:

ValueError: 
    Invalid element(s) received for the 'data' property of 
        Invalid elements include: [Figure(
    'data': ['coloraxis': 'coloraxis',
              'geojson': 'bbox': (-118.28177341, 33.7155889101773,
                                   -118.18514585495, 33.7780896175267),
                          'features': ['bbox': (-118.279454401, 33.7495355583513,
                                                 -118.271920681, 33.756297219837),
                                        'geometry': 'coordinates': (((-118.279454
                                                                     401,
                                                                     33.754490905),
                                                                     (-118.27537536
                                                                     6211, 33.74953
                                                                     55583513), (-1
                                                                     18.271920681, 
                                                                     33.75105207235
                                                                     19), (-118.275
                                                                     847434998, 33.
                                                                     756297219837),
                                                                     (-118.27945440
                                                                     1, 33.75449090
                                                                     5))),
                                                     'type': 'Polygon',
                                        'id': '0',
                                        'properties': ,
                                        'type': 'Feature',...

有什么想法吗?我可能完全错了,但是这种绘图的文档似乎还有很多不足之处。我尝试了各种排列,但没有运气。

【问题讨论】:

【参考方案1】: 您没有提供样本数据。已生成 10 个多边形来演示 您的数据屏幕截图显示了一个 pandas 数据框,其中有一列 st_astext 是众所周知的文本 https://shapely.readthedocs.io/en/stable/manual.html#well-known-formats 一种将其与 plotly 结合使用的方法
    使用shapely.wkt.loads()WKT解码为shapely 从这个 pandas Series 创建一个 geopandas GeoSeries。然后有接口__geo_interface__ 来生成GEOJSON
“颜色与多边形的 cnt 成比例”我假设是指多边形中的点数
import pandas as pd
import io
import geopandas as gpd
import shapely.geometry
import plotly.express as px

# fmt: off
df = pd.read_csv(io.StringIO('''st_astext
"POLYGON ((-3.86 50.67, -3.75 50.64, -3.46 50.58, -3.47 50.58, -3.47 50.56, -3.49 50.54, -3.51 50.52, -3.5 50.52, -3.47 50.46, -3.46 50.4, -3.51 50.38, -3.52 50.35, -3.54 50.34, -3.57 50.35, -3.58 50.38, -3.59 50.38, -3.58 50.37, -3.58 50.36, -3.56 50.34, -3.57 50.33, -3.61 50.32, -3.64 50.29, -3.66 50.24, -3.64 50.22, -3.68 50.22, -3.72 50.2, -3.74 50.21, -3.77 50.22, -3.76 50.24, -3.75 50.24, -3.74 50.24, -3.76 50.24, -3.75 50.26, -3.76 50.25, -3.77 50.26, -3.76 50.24, -3.78 50.23, -3.78 50.21, -3.81 50.21, -3.86 50.67))"
"POLYGON ((-3.12 53.56, -3.12 53.55, -3.12 53.55, -3.11 53.56, -3.04 53.53, -3 53.44, -3 53.42, -3.18 53.32, -3.22 53.34, -3.2 53.35, -3.23 53.37, -3.26 53.45, -3.16 53.43, -3.1 53.43, -3.12 53.43, -3.11 53.44, -3.11 53.45, -3.1 53.45, -3.09 53.44, -3.07 53.45, -3.09 53.45, -3.09 53.45, -3.06 53.46, -3.05 53.45, -3.06 53.45, -3.03 53.45, -3.03 53.45, -3.02 53.45, -3.07 53.49, -3.09 53.52, -3.15 53.54, -3.11 53.54, -3.12 53.54, -3.12 53.55, -3.12 53.56, -3.12 53.56))"
"POLYGON ((-3.63 51.13, -3.36 50.83, -3.37 50.76, -3.75 50.64, -3.86 50.67, -3.89 50.74, -3.63 51.13))"
"POLYGON ((-1.87 50.87, -1.67 50.8, -1.64 50.73, -1.69 50.74, -1.73 50.73, -1.75 50.71, -1.82 50.72, -1.9 50.71, -1.95 50.68, -1.94 50.67, -1.95 50.65, -1.92 50.64, -1.95 50.62, -1.96 50.61, -1.94 50.61, -1.96 50.59, -2.01 50.59, -1.87 50.87))"
"POLYGON ((-3.63 51.13, -3.61 51.22, -3.58 51.23, -3.54 51.23, -3.5 51.23, -3.47 51.21, -3.45 51.22, -3.4 51.19, -3.35 51.18, -3.28 51.18, -3.24 51.19, -3.12 50.82, -3.36 50.83, -3.63 51.13))"
"POLYGON ((-3.37 50.76, -3.36 50.83, -3.12 50.82, -2.91 50.75, -2.9 50.73, -2.92 50.73, -2.93 50.72, -3.02 50.7, -3.08 50.7, -3.1 50.69, -3.19 50.68, -3.25 50.67, -3.31 50.63, -3.35 50.62, -3.36 50.61, -3.38 50.6, -3.38 50.61, -3.37 50.76))"
"POLYGON ((-3.38 50.61, -3.43 50.62, -3.44 50.61, -3.43 50.63, -3.44 50.63, -3.43 50.63, -3.44 50.65, -3.44 50.63, -3.45 50.64, -3.44 50.65, -3.45 50.66, -3.44 50.62, -3.44 50.61, -3.42 50.61, -3.42 50.61, -3.46 50.58, -3.75 50.64, -3.37 50.76, -3.38 50.61))"
"POLYGON ((-2.34 50.99, -2.24 51.02, -2.22 51.01, -2.21 50.62, -2.24 50.62, -2.32 50.62, -2.34 50.63, -2.43 50.64, -2.45 50.61, -2.44 50.61, -2.45 50.6, -2.43 50.6, -2.45 50.6, -2.47 50.58, -2.46 50.57, -2.42 50.57, -2.43 50.57, -2.42 50.55, -2.46 50.51, -2.45 50.56, -2.54 50.62, -2.71 50.69, -2.34 50.99))"
"POLYGON ((-2.73 51.5, -2.71 51.31, -2.85 51.14, -2.86 51.14, -3.02 51.25, -3.01 51.24, -3.03 51.25, -3.03 51.25, -3.06 51.28, -3.04 51.29, -3.03 51.32, -3.04 51.33, -3.02 51.33, -2.98 51.38, -2.98 51.39, -2.91 51.4, -2.89 51.43, -3.11 51.34, -3.1 51.34, -3.12 51.34, -3.11 51.34, -3.12 51.38, -2.78 51.53, -2.73 51.53, -2.73 51.5))"
"POLYGON ((-2.86 51.14, -2.85 51.14, -2.34 50.99, -2.71 50.69, -2.74 50.7, -2.88 50.73, -2.9 50.73, -2.91 50.75, -2.86 51.14))"'''
                       ))
# fmt: on

px.choropleth_mapbox(
    geojson=gpd.GeoSeries(df["st_astext"].apply(shapely.wkt.loads)).__geo_interface__,
    locations=df.index,
    color=df["st_astext"]
    .apply(shapely.wkt.loads)
    .apply(lambda p: len(p.exterior.coords)),
).update_layout(
    mapbox="style": "carto-positron", "center": "lon": -2, "lat": 51, "zoom": 5
)

【讨论】:

谢谢。我不知道如何为 SO 帖子提供数据,这就是我截取部分 df 的原因。我将此标记为解决方案,但我实际需要更改的内容更简单。真正导致问题的原因是 1) locations 必须是整数索引,2) 我只需将 __geo_interface__ 添加到现有几何列 st_astext,以及 3) px.chloropleth_mapbox 已经返回一个元组。 为了明确第二点,我在创建 geopandas 数据框时已经将 st_astext 定义为几何列,因此根本不需要 shapely。 ah ok - locations 不需要是整数,如果是geodataframe的索引最简单(在geojson中变成id 有趣的是,如果在将其设为 df 索引之前将其转换为 int,我只能将自己的 id 列用作位置。无论如何,感谢您的帮助!

以上是关于来自 Geopandas Dataframe 的 Python Chloropleth Mapbox的主要内容,如果未能解决你的问题,请参考以下文章

GeoPandas 笔记: GeoDataFrame.plot()

python包介绍:GeoPandas(初识)

Pandas (GeoPandas)笔记:set_index & reset_index

组合 Geopandas 数据框中的行

Python之深入解析一行代码计算每个省面积的神器Geopandas

Python中的GeoPandas和GeoDataFrame