通过比较当前和上一行元组将新列映射到 Pandas 数据框

Map a new column to a Pandas dataframe by comparing current and previous row of tuples

我正在尝试使用接受两个输入元组的自定义函数将新列映射到 pandas 数据框。函数为:

def distance(origin, destination):
   lat1, lon1 = origin
   lat2, lon2 = destination
   radius = 3958.8 # miles

   dlat = math.radians(lat2-lat1)
   dlon = math.radians(lon2-lon1)
   a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
    * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
   c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
   d = radius * c

   return d

数据框有一列元组形式的纬度和经度,我正在尝试测量当前行和上一行坐标之间的距离。

我试过 for 循环:

df3.loc[0, 'dist'] = 0
for i in range(1, len(df3)):
    df3.loc[i, 'dist'] = distance(df3.loc[i-1, 'lat_long'], df3.loc[i, 'lat_long'])

但我收到错误“ValueError:没有足够的值来解压(预期 2,得到 1)”

关于如何做得更好的任何想法?

综合数据来说明

  1. reset_index() 获取行号作为列 index
  2. 构造一个从前一行到当前行的range()。如果是第一行,则将前一行设为 0
  3. 将元组列表传递给 tuplecalc()。你注意到你的 long,lat 是元组
  4. 显示它正在考虑当前行和上一行的计算
  5. 最终删除合成 index
df = pd.DataFrame({"geo":[(1,2),(3,4),(5,6)]}).reset_index()
def distance(prev, curr):
    return prev[0] + prev[1] + curr[0] + curr[1]
def tuplecalc(tuples):
    return distance(tuples[0], tuples[1] if len(tuples)==2 else (0,0))
df["distance"] = df.apply(lambda r: tuplecalc(df.loc[range(max(r["index"]-1,0),r["index"]+1),"geo"].values), axis=1)
df.drop(["index"], axis=1)

作为附加列

df = pd.DataFrame({"long":[1,3,5], "lat":[2,4,6]}).reset_index()
def rowrange(index, col):
    return 0 if index==0 else df.loc[range(max(index-1,0),index), col].values[0]
df["prev_long"] = df.apply(lambda r: rowrange(r["index"], "long"), axis=1)
df["prev_lat"] = df.apply(lambda r: rowrange(r["index"], "lat"), axis=1)
df

输出

    geo distance
0   (1, 2)  3
1   (3, 4)  10
2   (5, 6)  18