【问题标题】:Pandas dataframe : Applying function to row value and value from the previous rowPandas 数据框:将函数应用于行值和上一行的值
【发布时间】:2021-10-12 19:32:01
【问题描述】:

我正在尝试将以下函数应用于 Pandas 数据框:

def eukarney(lat1, lon1, alt1, lat2, lon2, alt2):
    p1 = (lat1, lon1)
    p2 = (lat2, lon2)
    karney = distance.distance(p1, p2).m
    return np.sqrt(karney**2 + (alt2 - alt1)**2)

如果我使用离散值,例如:

distance = eukarney(49.907611, 5.890404, 339.15734, 49.907683, 5.890373, 339.18224)

但是,如果我尝试将该函数应用于 Pandas 数据框:

df['distances'] = eukarney(df['latitude'], df['longitude'], df['altitude'], df['latitude'].shift(), df['longitude'].shift(), df['altitude'].shift())

这意味着从一行和前一行中获取值。

我收到以下错误消息:

Traceback(最近一次调用最后一次):文件 “/home/mirix/Desktop/plage/GPX_invert_sense_change_starting_point_va.py”, 第 78 行,在 df['distances'] = eukarney(df.loc[:,'latitude':], df.loc[:,'longitude':], df.loc[:,'altitude':], df.loc[:,'纬度':].shift(), df.loc[:,'经度':].shift(), df.loc[:,'altitude':].shift()) 文件 “/home/mirix/Desktop/plage/GPX_invert_sense_change_starting_point_va.py”, 第 75 行,在尤卡尼 karney = distance.distance(p1, p2).m 文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/distance.py”, 第 522 行,在 init 中 super().init(*args, **kwargs) 文件 "/home/mirix/.local/lib/python3.9/site-packages/geopy/distance.py", 第 276 行,在 init 中 km += self.measure(a, b) 文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/distance.py”, 第 538 行,测量中 a, b = Point(a), Point(b) 文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/point.py”,行 175,在 返回 cls.from_sequence(seq) 文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/point.py”,行 第472章 返回 cls(*args) 文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/point.py”,行 188,在 _normalize_coordinates(纬度,经度,高度)文件“/home/mirix/.local/lib/python3.9/site-packages/geopy/point.py”,行 57,在_normalize_coordinates 纬度=浮动(纬度或0.0)文件“/home/mirix/.local/lib/python3.9/site-packages/pandas/core/generic.py”, 第 1534 行,在 非零 raise ValueError(ValueError: DataFrame的真值不明确。使用a.empty、a.bool()、a.item()、a.any()或a.all()。

有趣的是,相同的语法适用于不使用 geopy 库的其他函数。

有什么想法吗?

解决方案

GeoPy 的距离函数似乎有一个内在限制,它似乎只接受标量。

以下解决方法基于以下@SeaBen 回答:

df['lat_shift'] = df['latitude'].shift().fillna(df['latitude'])
df['lon_shift'] = df['longitude'].shift().fillna(df['longitude'])
df['alt_shift'] = df['altitude'].shift().fillna(df['altitude'])

df['distances'] = df.apply(lambda x: eukarney(x['latitude'], x['longitude'], x['altitude'], x['lat_shift'], x['lon_shift'], x['alt_shift']), axis=1).fillna(0)

【问题讨论】:

  • 这是什么distance.distance?它接受np.array 还是只接受标量/浮点数?
  • distance.distance 来自 geopy 导入距离。 geopy.readthedocs.io/en/stable/#module-geopy.distance
  • 抱歉,忽略了您需要使用shift() 值。因此,以这种方式逐行使用.apply() 是不可能的。
  • @SeaBean 如果我将数据添加为新列,您的解决方案将有效。我试图避免这种情况,但这是我能找到的唯一解决方法。
  • 是的,同意添加新列是一种简单的方法。

标签: python pandas geopy


【解决方案1】:

你可以在每一行使用.apply(),如下:

这里,.apply() 帮助您将标量值逐行传递给自定义函数。因此,使您能够重用旨在处理标量值的自定义函数。否则,您可能需要修改自定义函数以支持 Pandas 的矢量化数组值。

为了满足.shift() 条目的需求,一种解决方法是首先为它们定义新列,以便我们可以将它们传递给.apply() 函数。

# Take previous entry by shift and `fillna` with original value for first row entry 
# (for in case the custom function cannot handle `NaN` entry on first row after shift)
df['lat_shift'] = df['latitude'].shift().fillna(df['latitude'])
df['lon_shift'] = df['longitude'].shift().fillna(df['longitude'])
df['alt_shift'] = df['altitude'].shift().fillna(df['altitude'])

df['distances'] = df.apply(lambda x: eukarney(x['latitude'], x['longitude'], x['altitude'], x['lat_shift'], x['lon_shift'], x['alt_shift']), axis=1).fillna(0)

【讨论】:

  • 谢谢。事实上,这个问题似乎是地理距离函数所固有的。如果预先创建了移位的列,则 apply 方法有效。
  • 再次感谢@SeaBen。我已经测试了您的解决方法,但它需要进行一些小的修改才能工作。请查看已编辑问题中的代码。
  • @mirix 很好,你微调了代码。没错,我们需要在移位后填充 NaN 值。我也忘记了这个因为没有测试过。很好,终于解决了问题。
猜你喜欢
  • 2020-08-24
  • 2023-03-09
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多