连续行熊猫数据帧之间的重复计算

Repeated calculation between consecutive rows of pandas dataframe

提问人:edge-case 提问时间:4/17/2017 最后编辑:MaxU - stand with Ukraineedge-case 更新时间:12/11/2017 访问量:2960

问:

我想计算沿 GPS 坐标路径的距离,这些坐标存储在数据框中的两列中。

import pandas as pd

df = pd.DataFrame({ 'lat' : [1, 2.5, 3, 1.2],
                    'lng' : [1, 1, 2.1, 1],
                    'label': ['foo', 'bar', 'zip', 'foo']})
print df

输出

  label  lat  lng
0   foo  1.0  1.0
1   bar  2.5  1.0
2   zip  3.0  2.1
3   foo  1.2  1.0

GPS 坐标以弧度存储。因此,数据帧的第一行和第二行之间的距离可以按如下方式计算:

import math as m

r1 = 0
r2 = 1

distance =m.acos(m.sin(df.lat[r1]) * m.sin(df.lat[r2]) + 
     m.cos(df.lat[r1]) * m.cos(df.lat[r2]) * m.cos(df.lng[r2]-df.lng[r1]))*6371

我想在每对连续行之间重复此计算,然后将每个短距离添加到完整路径的较长最终距离中。

我可以将其放入 dataframe 的 n-1 行的循环中,但是有没有更 pythonic 的方法来做到这一点?

Python Pandas,Numpy 数据帧 GPS

评论


答:

10赞 MaxU - stand with Ukraine 4/17/2017 #1

矢量化函数:Haversine

def haversine(lat1, lon1, lat2, lon2, to_radians=True, earth_radius=6371):
    """
    slightly modified version: of http://stackoverflow.com/a/29546836/2901002

    Calculate the great circle distance between two points
    on the earth (specified in decimal degrees or in radians)

    All (lat, lon) coordinates must have numeric dtypes and be of equal length.

    """
    if to_radians:
        lat1, lon1, lat2, lon2 = np.radians([lat1, lon1, lat2, lon2])

    a = np.sin((lat2-lat1)/2.0)**2 + \
        np.cos(lat1) * np.cos(lat2) * np.sin((lon2-lon1)/2.0)**2

    return earth_radius * 2 * np.arcsin(np.sqrt(a))

溶液:

df['dist'] = haversine(df['lat'], df['lng'],
                       df['lat'].shift(), df['lng'].shift(),
                       to_radians=False)

结果:

In [65]: df
Out[65]:
  label  lat  lng          dist
0   foo  1.0  1.0           NaN
1   bar  2.5  1.0   9556.500000
2   zip  3.0  2.1   7074.983158
3   foo  1.2  1.0  10206.286067

评论

0赞 edge-case 4/17/2017
谢谢,当我为 lat1、lon1 等输入数字时,haversine 函数有效,但是当我在实际数据帧上尝试它时,它返回错误:.我可以毫无问题地从循环中打印。关于如何解决此问题的任何想法?AttributeError: 'float' object has no attribute 'sin' np.sin(dlat/2.0)**2
0赞 MaxU - stand with Ukraine 4/18/2017
@omomo,请确保您没有命名的变量,并且没有拼写错误......还要确保将至少四个参数传递给该函数 -nplat1, lon1, lat2, lon2
0赞 edge-case 4/18/2017
有没有办法在堆栈溢出时共享数据帧,也许是作为 .pkl 文件?当我用数字从头开始创建数据帧时,它起作用了。但是我使用的实际数据帧是通过从 excel 文件导入数据构建的。excel 数据帧和从头开始构建的数据帧看起来相同,dtypes 相同,我无法弄清楚有什么不同。
0赞 MaxU - stand with Ukraine 4/18/2017
@omomo,您可以将文件上传到任何免费软件文件交换网站,并在此处发布链接pkl
1赞 edge-case 4/20/2017
感谢您的帮助。问题在于,当从 Excel 文件加载数据帧时,某些值为 NaN。即使删除了这些值,列类型仍为“object”而不是 float64。我不得不强制数据帧中的列是 float64df = df.apply(pd.to_numeric)