как ввести набор данных из txt-файла на python для GeoJSON

#python #pandas #dataframe #anaconda #geojson

Вопрос:

У меня очень мало опыта работы со сценариями GeoJSON и python.

Я пытаюсь взять файл txt и преобразовать его в данные для набора данных GeoJSON с этими значениями.

https://gis.stackexchange.com/questions/220997/pandas-to-geojson-multiples-points-features-with-python

Я ссылался на эту статью и использовал этот фрагмент кода:

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