Геопандас: объединение линий и конкатенация

Вопрос или проблема

У меня есть геодатафрейм. Я хочу объединить пересекающиеся объекты и конкатенировать поле “Text”. Я пробовал сделать это с помощью dissolve, но это не сработало.

import geopandas as gpd
import pandas as pd
from shapely.geometry import MultiLineString
data = {
    "type": "FeatureCollection",
    "name": "lines",
    "features": [
        { "type": "Feature", "properties": { "Text": "A" }, 
          "geometry": { "type": "MultiLineString", 
                        "coordinates": [ [ [ 0.0, 0.0, 0.0 ], [ 10.0, 0.0, 0.0 ] ] ] } },
        { "type": "Feature", "properties": { "Text": "B" }, 
          "geometry": { "type": "MultiLineString", 
                        "coordinates": [ [ [ 0.0, 0.0, 0.0 ], [ 16.37797725526616, 0.0, 0.0 ] ] ] } },
        { "type": "Feature", "properties": { "Text": "C" }, 
          "geometry": { "type": "MultiLineString", 
                        "coordinates": [ [ [ 0.0, 0.0, 0.0 ], [ 4.247235166607424, 7.041334981156978, 0.0 ], 
                                          [ 16.742636807728559, 8.986970615165774, 0.0 ] ] ] } },
        { "type": "Feature", "properties": { "Text": "D" }, 
          "geometry": { "type": "MultiLineString", 
                        "coordinates": [ [ [ 0.0, 0.0, 0.0 ], [ 4.247235166607424, 7.041334981156978, 0.0 ] ] ] } }
    ]
}
features = data['features']
geometries = []
properties = []
for feature in features:
    coords_3d = feature['geometry']['coordinates']
    coords_2d = [[(x, y) for x, y, z in line] for line in coords_3d]
    multiline = MultiLineString(coords_2d)
    geometries.append(multiline)
    properties.append(feature['properties'])
df = pd.DataFrame(properties)
gdf = gpd.GeoDataFrame(df, geometry=geometries)

Что я ищу:

результат, который я ищу

Объединить пересекающиеся объекты

Ответ или решение

Чтобы объединить пересекающиеся или соприкасающиеся линейные геометрические объекты в GeoPandas и конкатенировать связанные текстовые поля, можно использовать метод dissolve. Однако, как вы заметили, простое объединение может не всегда работать как ожидается, особенно в трехмерных координатах. Необходимо будет дополнительно обработать геометрические объекты, чтобы достичь желаемого результата.

Вот пример того, как это можно сделать:

import geopandas as gpd
import pandas as pd
from shapely.geometry import MultiLineString, LineString

# Данные
data = {
    "type": "FeatureCollection",
    "name": "lines",
    "features": [
        {"type": "Feature", "properties": {"Text": "A"}, 
         "geometry": {"type": "MultiLineString", 
                      "coordinates": [[[0.0, 0.0, 0.0], [10.0, 0.0, 0.0]]]}},
        {"type": "Feature", "properties": {"Text": "B"}, 
         "geometry": {"type": "MultiLineString", 
                      "coordinates": [[[0.0, 0.0, 0.0], [16.37797725526616, 0.0, 0.0]]]}},
        {"type": "Feature", "properties": {"Text": "C"}, 
         "geometry": {"type": "MultiLineString", 
                      "coordinates": [[[0.0, 0.0, 0.0], [4.247235166607424, 7.041334981156978, 0.0], 
                                        [16.742636807728559, 8.986970615165774, 0.0]]]}},
        {"type": "Feature", "properties": {"Text": "D"}, 
         "geometry": {"type": "MultiLineString", 
                      "coordinates": [[[0.0, 0.0, 0.0], [4.247235166607424, 7.041334981156978, 0.0]]]}},
    ]
}

# Создание GeoDataFrame
features = data['features']
geometries = []
properties = []
for feature in features:
    coords_3d = feature['geometry']['coordinates']
    coords_2d = [[(x, y) for x, y, z in line] for line in coords_3d]
    multiline = MultiLineString(coords_2d)
    geometries.append(multiline)
    properties.append(feature['properties'])

df = pd.DataFrame(properties)
gdf = gpd.GeoDataFrame(df, geometry=geometries)

# Объединение пересекающихся линий
# Создаем 2D представление для растворения (dissolve)
gdf['geometry'] = gdf['geometry'].apply(lambda geom: geom.dissolve())

# Объединение по идентификатору (обычно по уникальному идентификатору, в данном случае обходимся без него)
gdf_combined = gdf.dissolve(by=None, aggfunc='sum')

# Получаем текстовые поля
gdf_combined['Text'] = gdf['Text'].str.cat(sep='; ')

# Выводим результат
print(gdf_combined)

В этом коде мы:

  1. Загружаем ваши данные в GeoDataFrame.
  2. Упрощаем геометрию до 2D.
  3. Используем метод dissolve, который объединяет геометрии, которые пересекаются или соприкасаются, и агрегирует связанные данные. Здесь мы используем aggfunc='sum', чтобы объединить строки на основе текстового поля.
  4. Конкатенируем все значения текстового поля с помощью метода str.cat().

Убедитесь, что у вас установлены необходимые библиотеки (geopandas, shapely, pandas), чтобы код работал правильно. После выполнения вы получите объединенный GeoDataFrame с правильными геометриями и конкатенированными текстами, соответствующими вашим требованиям.

Оцените материал
Добавить комментарий

Капча загружается...