使用Folium和Geopandas绘制多边形无法正常工作。

3

我尝试使用Geopandas官方教程这个数据集来绘制与Geopandas和Folium相对应的多边形。我尽量按照教程的字面意思进行操作,但是Folium仍然无法绘制多边形。Matplotlib地图可以正常工作,我也可以创建Folium地图。代码如下:

import pandas as pd
import geopandas as gdp
import folium
import matplotlib.pyplot as plt

df = pd.read_csv('https://geo.stat.fi/geoserver/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=postialue:pno_tilasto&outputFormat=csv')
df.to_csv('coordinates.csv')

#limit to Helsinki and drop unnecessary columns 
df['population_2019'] = df['he_vakiy']
df['zipcode'] = df['postinumeroalue'].astype(int)
df['population_2019'] = df['population_2019'].astype(int)
df = df[df['zipcode'] < 1000]
df = df[['zipcode', 'nimi', 'geom', 'population_2019']]
df.to_csv('coordinates_hki.csv')
df.head()

#this is from there: https://gis.stackexchange.com/questions/387225/set-geometry-in-#geodataframe-to-another-column-fails-typeerror-input-must-be
from shapely.wkt import loads
df = gdp.read_file('coordinates_hki.csv')
df.geometry =  df['geom'].apply(loads)
df.plot(figsize=(6, 6))
plt.show()

df = df.set_crs(epsg=4326)
print(df.crs)
df.plot(figsize=(6, 6))
plt.show()

m = folium.Map(location=[60.1674881,24.9427473], zoom_start=10, tiles='CartoDB positron')
m

for _, r in df.iterrows():
    # Without simplifying the representation of each borough,
    # the map might not be displayed
    sim_geo = gdp.GeoSeries(r['geometry']).simplify(tolerance=0.00001)
    geo_j = sim_geo.to_json()
    geo_j = folium.GeoJson(data=geo_j,
                           style_function=lambda x: {'fillColor': 'orange'})
      
    folium.Popup(r['nimi']).add_to(geo_j)
    geo_j.add_to(folium.Popup(r['nimi']))                  
m
1个回答

3
这里的诀窍是要意识到你的数据不是以度为单位的。你可以通过查看多边形的重心来确定这一点:
>>> print(df.geometry.centroid)
0     POINT (381147.564 6673464.230)
1     POINT (381878.124 6676471.194)
2     POINT (381245.290 6677483.758)
3     POINT (381050.952 6678206.603)
4     POINT (382129.741 6677505.464)
                   ...              
79    POINT (397465.125 6676003.926)
80    POINT (393716.203 6675794.166)
81    POINT (393436.954 6679515.888)
82    POINT (395196.736 6677776.331)
83    POINT (398338.591 6675428.040)
Length: 84, dtype: geometry

这些值比地理空间数据的正常范围要大得多,经度范围为-180到180,纬度范围为-90到90。下一步是确定它实际上所在的CRS。如果您拿到数据集的URL,并去掉&outputFormat=csv部分,您将得到这个URL:
https://geo.stat.fi/geoserver/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=postialue:pno_tilasto

在该文档中搜索CRS,您会找到如下内容:
<gml:Envelope srsName="urn:ogc:def:crs:EPSG::3067" srsDimension="2">

所以,你的数据实际上是使用EPSG:3067标准来表示芬兰坐标的。
你需要告诉geopandas这一点,并将其转换为WGS84(最常见的坐标系统),以使其与folium兼容。
df.geometry =  df['geom'].apply(loads)
df = df.set_crs('EPSG:3067')
df = df.to_crs('WGS84')

函数 set_crs() 用于更改 GeoPandas 期望数据所在的坐标系,但不会更改任何坐标。函数 to_crs() 将数据集中的点重新投影到新的坐标系中。这两个调用的效果是从 EPSG:3067 转换为 WGS84。

通过添加这两行,我得到了以下结果:

map of helsinki


感谢你的详细回答!不幸的是代码仍然无法运行。我认为这可能与'geometry'列本身有关。以某种方式,Geopandas创建了一个新的“geometry”列,其中包含WGS84格式的值,并且旧的“geom”列仍然存在旧值。当我在循环内尝试“print(sim_geo)”时,它说值是多边形,而不是多面体。 - Ville
@Ville 当我按照您描述的方式设置代码时,它可以正常工作:https://nbviewer.org/gist/nickodell/ac335d4eb645c0a97e25de3d6025fda9 我还附上了我使用的每个软件包的版本,以防有用。问题中是否存在未涉及的因素? - Nick ODell
1
是的,现在它运行正常了,谢谢!我的代码倒数第二行也有错误。 - Ville

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接