Comment récupérer les coordonnées d'une colonne de polygones à partir d'une DataFrame GeoPandas ?

Published: 28 février 2024

Tags: GeoPandas; Shapely;

DMCA.com Protection Status

Introduction

GeoPandas est une puissante bibliothèque Python open-source qui permet l'analyse et la manipulation des données géospatiales. Une tâche courante lorsqu'on travaille avec des données géospatiales est de récupérer les coordonnées des polygones à partir d'une GeoPandas DataFrame.

Cela peut être fait en utilisant plusieurs méthodes différentes, qui seront discutées dans ce guide.

Création d'une DataFrame GeoPandas

Pour reproduire l'exemple ci-dessous, vous pouvez télécharger les données à partir du lien suivant.

import geopandas

gdf = geopandas.read_file('dataframe.geojson', driver='GeoJSON')

gdf.head()

Le code ci-dessus renverra :

  city_name  longitude_c1  latitude_c1  longitude_c2  latitude_c2  \
0     Paris        2.2522      48.7566        2.2522      48.9566   
1    London       -0.2276      51.4072       -0.2276      51.6072   
2    Moscow       37.5173      55.6558       37.5173      55.8558   
3  Istanbul       28.8784      40.9082       28.8784      41.1082

   longitude_c3  latitude_c3  longitude_c4  latitude_c4  \
0        2.4522      48.9566        2.4522      48.7566   
1       -0.0276      51.6072       -0.0276      51.4072   
2       37.7173      55.8558       37.7173      55.6558   
3       29.0784      41.1082       29.0784      40.9082

                                            geometry  
0  POLYGON ((2.25220 48.75660, 2.25220 48.95660, ...  
1  POLYGON ((-0.22760 51.40720, -0.22760 51.60720...  
2  POLYGON ((37.51730 55.65580, 37.51730 55.85580...  
3  POLYGON ((28.87840 40.90820, 28.87840 41.10820...

Dans cet exemple, nous pouvons voir que les données contiennent des informations sur quatre villes différentes - Paris, Londres, Moscou et Istanbul. Chaque ville a ses propres coordonnées représentées par des valeurs de longitude et de latitude. Ces coordonnées sont ensuite utilisées pour créer des polygones sur une carte en utilisant la bibliothèque shapely.

Extraction des coordonnées du polygone

Il existe diverses méthodes pour extraire les coordonnées des polygones, chacune avec des niveaux d'efficacité variables en fonction de la taille de votre DataFrame et de savoir si tous les polygones partagent le même nombre de sommets. Explorons ces approches.

Parcourir chaque ligne dans la GeoDataFrame

Cette approche est adaptée aux petits DataFrames car elle utilise une boucle for pour itérer sur chaque ligne :

for idx, row in gdf.iterrows():

    X,Y = row['geometry'].exterior.coords.xy

    print( list(X),  list(Y) )

Ce extrait de code itère à travers chaque ligne d'une GeoDataFrame nommé gdf en utilisant une boucle for. Dans chaque ligne, il extrait les coordonnées X et Y de la limite extérieure de la géométrie. Cela est réalisé en accédant à la colonne 'geometry', puis en descendant jusqu'à l'extérieur et son attribut coords. La méthode .xy sépare finalement les coordonnées en listes individuelles de valeurs X et Y :

[2.2522, 2.2522, 2.4522, 2.4522, 2.2522] [48.7566, 48.9566, 48.9566, 48.7566, 48.7566]
[-0.2276, -0.2276, -0.0276, -0.0276, -0.2276] [51.4072, 51.6072, 51.6072, 51.4072, 51.4072]
[37.5173, 37.5173, 37.7173, 37.7173, 37.5173] [55.6558, 55.8558, 55.8558, 55.6558, 55.6558]
[28.8784, 28.8784, 29.0784, 29.0784, 28.8784] [40.9082, 41.1082, 41.1082, 40.9082, 40.9082]

Création d'une fonction pour extraire les coordonnées du polygone

Pour extraire les coordonnées du polygone à partir d'un ensemble de données donné, nous pouvons créer une fonction qui prendra les paramètres d'entrée nécessaires et renverra la sortie souhaitée. Les étapes suivantes décrivent comment créer une telle fonction:

En utilisant la fonction apply()

La fonction apply() dans pandas nous permet d'appliquer une fonction donnée le long d'un axe de la DataFrame. Nous pouvons utiliser cette fonction pour itérer sur les lignes ou les colonnes de notre jeu de données et extraire les coordonnées nécessaires.

Voici un exemple de code pour créer notre fonction personnalisée en utilisant apply():

def get_polygon_coordinates(p):

    X,Y = p.exterior.coords.xy

    return list(X[:-1]), list(Y[:-1])

Cette fonction prend en paramètre 'p' qui représente l'objet Polygone de notre ensemble de données. Nous utilisons la méthode exterior.coords.xy pour extraire séparément les coordonnées x et y, puis les renvoyons sous forme de listes. Le [:-1] à la fin est utilisé pour exclure la dernière coordonnée car c'est un doublon.

Par exemple, en accédant au premier polygone

get_polygon_coordinates(gdf['geometry'][0])

nous obtenons:

([2.2522, 2.2522, 2.4522, 2.4522], [48.7566, 48.9566, 48.9566, 48.7566])

Pour appliquer notre fonction à toutes les lignes de la DataFrame GeoPandas, nous pouvons procéder comme suit:

gdf['geometry'].apply(get_polygon_coordinates)

Cela renverra une série avec des listes de coordonnées x et y pour chaque polygone de notre ensemble de données :

0    ([2.2522, 2.2522, 2.4522, 2.4522], [48.7566, 4...
1    ([-0.2276, -0.2276, -0.0276, -0.0276], [51.407...
2    ([37.5173, 37.5173, 37.7173, 37.7173], [55.655...
3    ([28.8784, 28.8784, 29.0784, 29.0784], [40.908...
Name: geometry, dtype: object

Cette série contient toutes les coordonnées extraites pour chaque polygone de notre ensemble de données. À partir de là, nous pouvons facilement manipuler et utiliser ces coordonnées à des fins d'analyse ou de visualisation ultérieures.

En utilisant map()

Pour une vitesse améliorée, l'utilisation de la fonction map de Python est une autre approche efficace. En appliquant cette fonction à notre colonne de géométrie, nous pouvons obtenir une liste des coordonnées extérieures pour chaque polygone de notre ensemble de données. Le code ressemblerait à ceci:

list( map(get_polygon_coordinates,gdf['geometry']) )

ce qui renverrait une liste de tuples avec des listes de coordonnées x et y pour chaque polygone.

[([2.2522, 2.2522, 2.4522, 2.4522], [48.7566, 48.9566, 48.9566, 48.7566]),
 ([-0.2276, -0.2276, -0.0276, -0.0276], [51.4072, 51.6072, 51.6072, 51.4072]),
 ([37.5173, 37.5173, 37.7173, 37.7173], [55.6558, 55.8558, 55.8558, 55.6558]),
 ([28.8784, 28.8784, 29.0784, 29.0784], [40.9082, 41.1082, 41.1082, 40.9082])]

Si nos polygones ont un nombre égal de sommets, nous pouvons stocker les coordonnées dans une matrice NumPy. Voici un extrait de code pour y parvenir:

import numpy as np

coords = np.asarray( list( map(get_polygon_coordinates,gdf['geometry']) ) )

Veuillez noter que la forme de la matrice est affichée ici:

coords.shape

ce qui se traduit par:

(4, 2, 4)

Nous pouvons remodeler nos coordonnées de matrice en utilisant la commande

coords.reshape(4,8)

ce qui donne la structure de tableau suivante:

array([[ 2.25220e+00,  2.25220e+00,  2.45220e+00,  2.45220e+00,
         4.87566e+01,  4.89566e+01,  4.89566e+01,  4.87566e+01],
       [-2.27600e-01, -2.27600e-01, -2.76000e-02, -2.76000e-02,
         5.14072e+01,  5.16072e+01,  5.16072e+01,  5.14072e+01],
       [ 3.75173e+01,  3.75173e+01,  3.77173e+01,  3.77173e+01,
         5.56558e+01,  5.58558e+01,  5.58558e+01,  5.56558e+01],
       [ 2.88784e+01,  2.88784e+01,  2.90784e+01,  2.90784e+01,
         4.09082e+01,  4.11082e+01,  4.11082e+01,  4.09082e+01]])

Ensuite, stockez le résultat dans de nouvelles colonnes au sein de notre DataFrame :

import pandas as pd

pd.concat([gdf, 
           pd.DataFrame( coords.reshape(4,8) )], 
           axis=1)

Le DataFrame suivant sera généré:

  city_name  longitude_c1  latitude_c1  longitude_c2  latitude_c2  \
0     Paris        2.2522      48.7566        2.2522      48.9566   
1    London       -0.2276      51.4072       -0.2276      51.6072   
2    Moscow       37.5173      55.6558       37.5173      55.8558   
3  Istanbul       28.8784      40.9082       28.8784      41.1082

   longitude_c3  latitude_c3  longitude_c4  latitude_c4  \
0        2.4522      48.9566        2.4522      48.7566   
1       -0.0276      51.6072       -0.0276      51.4072   
2       37.7173      55.8558       37.7173      55.6558   
3       29.0784      41.1082       29.0784      40.9082

                                            geometry        0        1  \
0  POLYGON ((2.25220 48.75660, 2.25220 48.95660, ...   2.2522   2.2522   
1  POLYGON ((-0.22760 51.40720, -0.22760 51.60720...  -0.2276  -0.2276   
2  POLYGON ((37.51730 55.65580, 37.51730 55.85580...  37.5173  37.5173   
3  POLYGON ((28.87840 40.90820, 28.87840 41.10820...  28.8784  28.8784

         2        3        4        5        6        7  
0   2.4522   2.4522  48.7566  48.9566  48.9566  48.7566  
1  -0.0276  -0.0276  51.4072  51.6072  51.6072  51.4072  
2  37.7173  37.7173  55.6558  55.8558  55.8558  55.6558  
3  29.0784  29.0784  40.9082  41.1082  41.1082  40.9082

Nous pouvons également attribuer des noms aux nouvelles colonnes :

pd.concat([gdf, 
           pd.DataFrame( coords.reshape(4,8), columns=['x1','x2','x3','x4','y1','y2','y3','y4'] )], 
           axis=1)

La DataFrame suivant sera généré:

  city_name  longitude_c1  latitude_c1  longitude_c2  latitude_c2  \
0     Paris        2.2522      48.7566        2.2522      48.9566   
1    London       -0.2276      51.4072       -0.2276      51.6072   
2    Moscow       37.5173      55.6558       37.5173      55.8558   
3  Istanbul       28.8784      40.9082       28.8784      41.1082

   longitude_c3  latitude_c3  longitude_c4  latitude_c4  \
0        2.4522      48.9566        2.4522      48.7566   
1       -0.0276      51.6072       -0.0276      51.4072   
2       37.7173      55.8558       37.7173      55.6558   
3       29.0784      41.1082       29.0784      40.9082

                                            geometry       x1       x2  \
0  POLYGON ((2.25220 48.75660, 2.25220 48.95660, ...   2.2522   2.2522   
1  POLYGON ((-0.22760 51.40720, -0.22760 51.60720...  -0.2276  -0.2276   
2  POLYGON ((37.51730 55.65580, 37.51730 55.85580...  37.5173  37.5173   
3  POLYGON ((28.87840 40.90820, 28.87840 41.10820...  28.8784  28.8784

        x3       x4       y1       y2       y3       y4  
0   2.4522   2.4522  48.7566  48.9566  48.9566  48.7566  
1  -0.0276  -0.0276  51.4072  51.6072  51.6072  51.4072  
2  37.7173  37.7173  55.6558  55.8558  55.8558  55.6558  
3  29.0784  29.0784  40.9082  41.1082  41.1082  40.9082

Références