Converter um DataFrame do panda em um GeoDataFrame

42

Parece uma pergunta bastante simples, mas não consigo descobrir como converter um DataFrame do panda em um GeoDataFrame para uma junção espacial.

Aqui está um exemplo de como meus dados se parecem usando df.head():

    Date/Time           Lat       Lon       ID
0   4/1/2014 0:11:00    40.7690   -73.9549  140
1   4/1/2014 0:17:00    40.7267   -74.0345  NaN

Na verdade, esse quadro de dados foi criado a partir de um CSV, por isso, se for mais fácil ler o CSV diretamente como um GeoDataFrame, tudo bem.

atkat12
fonte
11
use GeoPandas
gene

Respostas:

78

Converter conteúdo da trama de dados (por exemplo, Late Loncolunas) em apropriados Shapely geometrias primeiro e depois usá-los em conjunto com a trama de dados original para criar uma GeoDataFrame.

from geopandas import GeoDataFrame
from shapely.geometry import Point

geometry = [Point(xy) for xy in zip(df.Lon, df.Lat)]
df = df.drop(['Lon', 'Lat'], axis=1)
crs = {'init': 'epsg:4326'}
gdf = GeoDataFrame(df, crs=crs, geometry=geometry)

Resultado:

    Date/Time           ID      geometry
0   4/1/2014 0:11:00    140     POINT (-73.95489999999999 40.769)
1   4/1/2014 0:17:00    NaN     POINT (-74.03449999999999 40.7267)

Como as geometrias geralmente vêm no formato WKT, pensei em incluir um exemplo para esse caso:

import geopandas as gpd
import shapely.wkt

geometry = df['wktcolumn'].map(shapely.wkt.loads)
df = df.drop('wktcolumn', axis=1)
crs = {'init': 'epsg:4326'}
gdf = gpd.GeoDataFrame(df, crs=crs, geometry=geometry)
Martin Valgur
fonte
Obrigado novamente! Isso é muito mais simples e corre muito rápido - muito melhor do que a iteração através de cada linha do df na minha n = 500.000 :)
atkat12
6
Puxa, obrigada! I verificar esta resposta como a cada 2 dias :)
Owen
11
você acha que essa seria a primeira entrada na documentação!
Dominik
+1 para o shapely.wkt. Levei um tempo para descobrir isso!
precisa
14

One-liners! Além disso, alguns indicadores de desempenho para pessoas de big data.

Dado a pandas.DataFrameque tem x Longitude e Latitude y da seguinte forma:

df.head()
x   y
0   229.617902  -73.133816
1   229.611157  -73.141299
2   229.609825  -73.142795
3   229.607159  -73.145782
4   229.605825  -73.147274

Vamos converter o pandas.DataFrameem um da geopandas.GeoDataFrameseguinte maneira:

Importações de bibliotecas e acelerações bem torneadas :

import geopandas as gpd
import shapely
shapely.speedups.enable() # enabled by default from version 1.6.0

Código + tempos de referência em um conjunto de dados de teste que eu tenho:

#Martin's original version:
#%timeit 1.87 s ± 7.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
gdf = gpd.GeoDataFrame(df.drop(['x', 'y'], axis=1),
                                crs={'init': 'epsg:4326'},
                                geometry=[shapely.geometry.Point(xy) for xy in zip(df.x, df.y)])



#Pandas apply method
#%timeit 8.59 s ± 60.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
gdf = gpd.GeoDataFrame(df.drop(['x', 'y'], axis=1),
                       crs={'init': 'epsg:4326'},
                       geometry=df.apply(lambda row: shapely.geometry.Point((row.x, row.y)), axis=1))

O uso pandas.applyé surpreendentemente mais lento, mas pode ser mais adequado para outros fluxos de trabalho (por exemplo, em conjuntos de dados maiores usando a biblioteca dask):

Créditos para:

Algumas referências de trabalho em andamento (a partir de 2017) para lidar com grandes daskconjuntos de dados:

weiji14
fonte
Obrigado pela comparação, na verdade a versão zip é muito mais rápida
MCMZL