#python #pandas #dataframe #anaconda #geojson
Вопрос:
У меня очень мало опыта работы со сценариями GeoJSON и python.
Я пытаюсь взять файл txt и преобразовать его в данные для набора данных GeoJSON с этими значениями.
Я ссылался на эту статью и использовал этот фрагмент кода:
import pandas as pd
import geojson
def data2geojson(df):
features = []
insert_features = lambda X: features.append(
geojson.Feature(geometry=geojson.LineString((X["long"],
X["lat"],
X["elev"])),
properties=dict(name=X["name"],
description=X["description"])))
df.apply(insert_features, axis=1)
with open('map1.geojson', 'w', encoding='utf8') as fp:
geojson.dump(geojson.FeatureCollection(features), fp, sort_keys=True, ensure_ascii=False,indent=4)
col = ['lat','long','elev','name','description']
data = [[-29.9953,-70.5867,760,'A','Place MNO'],
[-30.1217,-70.4933,1250,'C','Place PQR'],
[-30.0953,-70.5008,1185,'C','Place STU']]
df = pd.DataFrame(data, columns=col)
data2geojson(df)
Однако для данных у меня есть точки, которые находятся в одной строке (поэтому я использую LineString вместо точки), и у них есть уникальные идентификаторы, которые нужно разместить в разделе «свойства» GeoJSON.
Это пример данных в моем файле .txt
lat=1.3218368 ,long=103.9364834 ,A, Place BC
lat=1.3218821 ,long=103.9364744 ,A, Place BC
lat=1.3219285 ,long=103.9367017 ,A, Place BC
lat=1.321643 ,long=103.9364707 ,A, Place BC
lat=1.3216271 ,long=103.9363887 ,A, Place BC
lat=1.3235089 ,long=103.9344606 ,A, Place BC
lat=1.3237205 ,long=103.9355026 ,A, Place BC
lat=1.3217046 ,long=103.934106 ,A, Place BC
lat=1.3203204 ,long=103.9366324 ,B, Place AC
lat=1.3206557 ,long=103.9373536 ,B, Place AC
lat=1.3206271 ,long=103.9374192 ,B, Place AC
lat=1.3205511 ,long=103.9371742 ,B, Place AC
lat=1.3206044 ,long=103.9375056 ,B, Place AC
lat=1.3207561 ,long=103.9371863 ,B, Place AC
lat=1.3204307 ,long=103.9368537 ,B, Place AC
lat=1.3204877 ,long=103.9368389 ,B, Place AC
lat=1.3205465 ,long=103.9368269 ,B, Place AC
lat=1.320612 ,long=103.9368246 ,B, Place AC
lat=1.3207378 ,long=103.9371016 ,B, Place AC
lat=1.3207702 ,long=103.9370846 ,B, Place AC
Как мне следует использовать этот txt в качестве входных данных для массива функции data
и группировать их в соответствии name
, например. A или B, независимо от description
того, LineString
имеют ли более 1 точки, прикрепленные к каждому объекту.
Любая и вся помощь будет оценена по достоинству!!
Ответ №1:
Я бы посоветовал использовать геопанды, так как они адаптированы к таким проблемам, как эта:
import pandas as pd
import geopandas as gpd
from shapely.geometry import LineString
import io
col = ['lat','long','name','description']
data = '''lat=1.3218368 ,long=103.9364834 ,A, Place BC
lat=1.3218821 ,long=103.9364744 ,A, Place BC
lat=1.3219285 ,long=103.9367017 ,A, Place BC
lat=1.321643 ,long=103.9364707 ,A, Place BC
lat=1.3216271 ,long=103.9363887 ,A, Place BC
lat=1.3235089 ,long=103.9344606 ,A, Place BC
lat=1.3237205 ,long=103.9355026 ,A, Place BC
lat=1.3217046 ,long=103.934106 ,A, Place BC
lat=1.3203204 ,long=103.9366324 ,B, Place AC
lat=1.3206557 ,long=103.9373536 ,B, Place AC
lat=1.3206271 ,long=103.9374192 ,B, Place AC
lat=1.3205511 ,long=103.9371742 ,B, Place AC
lat=1.3206044 ,long=103.9375056 ,B, Place AC
lat=1.3207561 ,long=103.9371863 ,B, Place AC
lat=1.3204307 ,long=103.9368537 ,B, Place AC
lat=1.3204877 ,long=103.9368389 ,B, Place AC
lat=1.3205465 ,long=103.9368269 ,B, Place AC
lat=1.320612 ,long=103.9368246 ,B, Place AC
lat=1.3207378 ,long=103.9371016 ,B, Place AC
lat=1.3207702 ,long=103.9370846 ,B, Place AC'''
#load csv as dataframe (replace io.StringIO(data) with the csv filename), use converters to clean up lat and long columns upon loading
df = pd.read_csv(io.StringIO(data), names=col, sep='s*,s*', engine='python', converters={'lat': lambda x: float(x.split('=')[1]), 'long': lambda x: float(x.split('=')[1])})
#load dataframe as geodataframe
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.long, df.lat))
#groupby on name and description, while converting the grouped geometries to a LineString
gdf = gdf.groupby(['name', 'description'])['geometry'].apply(lambda x: LineString(x.tolist())).reset_index()
gdf.to_json()
Выходной геоджсон:
{"type": "FeatureCollection", "features": [{"id": "0", "type": "Feature", "properties": {"description": "Place BC", "name": "A"}, "geometry": {"type": "LineString", "coordinates": [[103.9364834, 1.3218368], [103.9364744, 1.3218821], [103.9367017, 1.3219285], [103.9364707, 1.321643], [103.9363887, 1.3216271], [103.9344606, 1.3235089], [103.9355026, 1.3237205], [103.934106, 1.3217046]]}}, {"id": "1", "type": "Feature", "properties": {"description": "Place AC", "name": "B"}, "geometry": {"type": "LineString", "coordinates": [[103.9366324, 1.3203204], [103.9373536, 1.3206557], [103.9374192, 1.3206271], [103.9371742, 1.3205511], [103.9375056, 1.3206044], [103.9371863, 1.3207561], [103.9368537, 1.3204307], [103.9368389, 1.3204877], [103.9368269, 1.3205465], [103.9368246, 1.320612], [103.9371016, 1.3207378], [103.9370846, 1.3207702]]}}]}