将点转换为线 Geopandas

16

您好,我正在尝试将一组X和Y坐标转换为线。我想通过groupby ID和时间映射此数据。只要我在一个列上groupby,我的代码就会成功执行,但是当我在两个列上使用groupby时,就会遇到错误。我参考了这个问题

以下是一些示例数据:

ID  X           Y           Hour
1   -87.78976   41.97658    16
1   -87.66991   41.92355    16
1   -87.59887   41.708447   17
2   -87.73956   41.876827   16
2   -87.68161   41.79886    16
2   -87.5999    41.7083     16
3   -87.59918   41.708485   17
3   -87.59857   41.708393   17
3   -87.64391   41.675133   17

这是我的代码:

df = pd.read_csv("snow_gps.csv", sep=';')

#zip the coordinates into a point object and convert to a GeoData Frame
geometry = [Point(xy) for xy in zip(df.X, df.Y)]
geo_df = GeoDataFrame(df, geometry=geometry)

# aggregate these points with the GrouBy
geo_df = geo_df.groupby(['track_seg_point_id', 'Hour'])['geometry'].apply(lambda x: LineString(x.tolist()))
geo_df = GeoDataFrame(geo_df, geometry='geometry')

这是错误信息: ValueError: LineStrings 必须至少有两个坐标元组。

这是我正在尝试获取的最终结果:

ID          Hour     geometry
1           16       LINESTRING (-87.78976 41.97658, -87.66991 41.9... 
1           17       LINESTRING (-87.78964000000001 41.976634999999... 
1           18       LINESTRING (-87.78958 41.97663499999999, -87.6... 
2           16       LINESTRING (-87.78958 41.976612, -87.669785 41... 
2           17       LINESTRING (-87.78958 41.976624, -87.66978 41.... 
3           16       LINESTRING (-87.78958 41.97666, -87.6695199999... 
3           17       LINESTRING (-87.78954 41.976665, -87.66927 41.... 

请提供有关如何按多个参数进行分组的任何建议或想法。


1
你得到的错误信息似乎表明正在尝试从单个点创建LineString,这将失败。你是否有一个仅包含单行的组? - joris
如果你尝试使用x,y而不是xy呢? - ted
@joris 我不相信那是问题所在?Ted,你是在建议将x和y放在单独的列中而不是进行连接吗? - mm_nieder
如果我只取文件 df 并运行 grouped = df.groupby(['ID', 'Hour']) grouped.groups,则结果如下: {(0, 16): Int64Index([5, 14, 16, 55, 130], dtype='int64'), (0, 17): Int64Index([7, 27, 126, 141, 185, 235], dtype='int64'),... 但现在我没有坐标,并且不知道如何将点转换为线?也许我可以索引每个位置以获取它们的 xy 然后进行转换? - mm_nieder
你能否检查一下 (df.groupby(['ID', 'Hour']).size() < 2).sum() 是否确实返回了0? - joris
1个回答

15

你的代码很好,问题在于你的数据。

如果你按照ID和小时分组,你会发现只有一个点与ID为1且小时为17的一组匹配。而一个线要由一个或多个点组成(必须至少有2个坐标元组)。我已经为你的样本数据添加了另一个点:

ID   X          Y           Hour
1   -87.78976   41.97658    16
1   -87.66991   41.92355    16
1   -87.59887   41.708447   17
1   -87.48234   41.677342   17
2   -87.73956   41.876827   16
2   -87.68161   41.79886    16
2   -87.5999    41.7083     16
3   -87.59918   41.708485   17
3   -87.59857   41.708393   17
3   -87.64391   41.675133   17

正如您下面所看到的,以下代码几乎与您的代码相同:

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

df = pd.read_csv("snow_gps.csv", sep='\s*,\s*')

#zip the coordinates into a point object and convert to a GeoData Frame
geometry = [Point(xy) for xy in zip(df.X, df.Y)]
geo_df = gpd.GeoDataFrame(df, geometry=geometry)

geo_df2 = geo_df.groupby(['ID', 'Hour'])['geometry'].apply(lambda x: LineString(x.tolist()))
geo_df2 = gpd.GeoDataFrame(geo_df2, geometry='geometry')

在https://pygis.io/docs/e_new_vectors.html可以找到一些关于创建地理空间数据的好教程。 - mmann1123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接