通过数据帧中的唯一id获取第一行和最后一行值

2024-05-23 21:57:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个用于位置跟踪的数据帧,类似于:

df = pd.DataFrame({
    'id': [1,1,1,2,2],
    'lat': [41.144540, 41.144540, 41.163172, 41.163233, 41.163198],
    'lon': [-8.562926, -8.562926, -8.583821, -8.583838, -8.583886   ] 
})

df

    id    lat         lon
0   1   41.144540   -8.562926
1   1   41.144540   -8.562926
2   1   41.163172   -8.583821
3   2   41.163233   -8.583838
4   2   41.163198   -8.583886

因此,我想为每次行程的长度(即每个id)添加一个新列。 例如,为了计算行程id=1的长度,我将以这种方式使用开始和结束坐标:

from geopy.distance import vincenty

coords_1 = (41.144540,  -8.562926)
coords_2 = (41.163172   -8.583821)

length = vincenty(coords_1, coords_2).m
length
1217881.558204788

和2相似,其余的。但是我想用熊猫数据帧来实现这一点

预期产出:

    id    lat         lon       length
0   1   41.144540   -8.562926  1217881.5582
1   1   41.144540   -8.562926  1217881.5582
2   1   41.163172   -8.583821  1217881.5582
3   2   41.163233   -8.583838  5.5979928
4   2   41.163198   -8.583886  5.5979928

Tags: 数据fromiddataframedf方式coordslength
3条回答

您可以使用.apply(...)

def get_length(group):
  
  coords = group[['lat', 'lon']].values
  p1, p2 = coords[0], coords[-1]
    
  length = vincenty(p1, p2).m

  return length

grouped = df.groupby(by=['id'])
length = grouped.apply(get_length).rename('length')

df.merge(length, on=['id'])

    id     lat         lon       length
0   1   41.144540   -8.562926   2712.533677
1   1   41.144540   -8.562926   2712.533677
2   1   41.163172   -8.583821   2712.533677
3   2   41.163233   -8.583838   5.597993
4   2   41.163198   -8.583886   5.597993

我无法让vincenty工作,显然它已被geodesic取代。但这应该是可行的:

from geopy.distance import geodesic

df = pd.DataFrame({
    'id': [1,1,1,2,2],
    'lat': [41.144540, 41.144540, 41.163172, 41.163233, 41.163198],
    'lon': [-8.562926, -8.562926, -8.583821, -8.583838, -8.583886   ] 
})


res = (df.groupby(by='id').agg(start_lat=pd.NamedAgg(column='lat', aggfunc='first'), 
                              start_long=pd.NamedAgg(column='lon', aggfunc='first'),
                              end_lat = pd.NamedAgg(column='lat', aggfunc='last'), 
                              end_long=pd.NamedAgg(column='lon', aggfunc='last'))
        .apply(lambda f: geodesic((f['start_lat'], f['start_long']), (f['end_lat'], f['end_long'])), axis=1)
        .reset_index()
        )

df = df.merge(res, on='id').rename(columns={0: 'dist'})

print(df)

您可以使用groupby()^{}(也称aggregate())在单个命令中获取第一个和最后一个值:

df.groupby('id').agg({'lat': ['first', 'last'], 'lon': ['first', 'last']})

这给了你:

          lat                  lon          
        first       last     first      last
id                                          
1   41.144540  41.163172 -8.562926 -8.583821
2   41.163233  41.163198 -8.583838 -8.583886

这几乎正是您需要输入到vincenty()来计算每个id的距离的内容

相关问题 更多 >