3

I have tried to plot polygons to map with Geopandas and Folium using Geopandas official tutorial and this dataset. I tried to follow the tutorial as literally as I could but still Folium don't draw polygons. Matplotlib map works and I can create Folium map too. Code:

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
Nick ODell
  • 15,465
  • 3
  • 32
  • 66
Ville
  • 57
  • 9

1 Answers1

3

The trick here is to realize that your data is not in units of degrees. You can determine this by looking at the centroid of your polygons:

>>> 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

These values are way bigger than the normal range for geospatial data, which is -180 to 180 for longitude, and -90 to 90 for latitude. The next step is to figure out what CRS it is actually in. If you take your dataset URL, and strip off the &outputFormat=csv part, you get this URL:

https://geo.stat.fi/geoserver/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=postialue:pno_tilasto

Search for CRS in that document, and you'll find this:

<gml:Envelope srsName="urn:ogc:def:crs:EPSG::3067" srsDimension="2">

So, it turns out your data is in EPSG:3067, a standard for representing Finnish coordiates.

You need to tell geopandas about this, and convert into WGS84 (the most common coordinate system) to make it compatible with folium.

df.geometry =  df['geom'].apply(loads)
df = df.set_crs('EPSG:3067')
df = df.to_crs('WGS84')

The function set_crs(), changes the coordinate system that GeoPandas expects the data to be in, but does not change any of the coordinates. The function to_crs() takes the points in the dataset and re-projects them into a new coordinate system. The effect of these two calls is to convert from EPSG:3067 to WGS84.

By adding these two lines, I get the following result:

map of helsinki

Nick ODell
  • 15,465
  • 3
  • 32
  • 66
  • Thanks for informative answer! Unfortunately code still won't work. I'm thinking it's something to do with 'geometry' column itself. Somehow Geopandas makes new 'geometry' column that has values in WGS84 format and old 'geom' column is still there with old values. An when I tried "print(sim_geo)" inside of loop, it says values are Polygons, not Multipolygons. – Ville Dec 26 '21 at 10:58
  • @Ville This works when I set the code up as you described it: https://nbviewer.org/gist/nickodell/ac335d4eb645c0a97e25de3d6025fda9 I've also attached the versions of each package that I'm using, in case that's useful. Is there an element of the problem which is not in the question? – Nick ODell Dec 26 '21 at 16:46
  • 1
    Yes now it worked, thanks! The second last line of my code was also wrong. – Ville Dec 26 '21 at 21:10