使用 运行 标志减少数据帧

Reduce dataframe using a running flag

我有一个数据框,其中包含一些点的 xy 坐标。每个点(坐标对)也被标记为 True/False 标志:

xs = [1,3,7,5,4,6,2,8,9,0]
ys = [0,7,4,5,2,6,9,1,3,8]
flags = [True,False,False,False,True,True,False,True,True,True]
df = pd.DataFrame({'x':xs, 'y':ys,'flag':flags})


    x   y   flag
0   1   0   True
1   3   7   False
2   7   4   False
3   5   5   False
4   4   2   True
5   6   6   True
6   2   9   False
7   8   1   True
8   9   3   True
9   0   8   True

什么reduce函数可以用来计算2个总距离:

1) 路线的总距离以假点之后的真点开始或以第一个点为真,包括所有真点并以假点或所有点​​的终点终止

2) 路线的总距离是在真点之后以假点开始或以假点开始,包括所有假点并以真点或所有点​​的终点终止

在这个例子中,需要将以下部分相加得到总距离:

1) Route built from  True points:
(1,0) - (3,7)
---
(4,2) - (6,6)
(6,6) - (2,9)
---
(8,1) - (9,3)
(9,3) - (0,8)

2) Route built from False points:
(3,7) - (7,4)
(7,4) - (5,5)
(5,5) - (4,2)
---
(2,9) - (8,1)

因此,例如,这些要点:

points = [((1,0),(3,7)), ((4,2),(6,6)), ((6,6),(2,9)), 
           ((8,1),(9,3)), ((9,3),(0,8))]

# Compute distance between two points:
def distance(x1,y1,x2,y2):
    return math.sqrt((x2-x1)**2 + (y2-y1)**2)

总距离:

total_distance = 0
for t in points:
   total_distance += distance(t[0][0],t[0][1], t[1][0],t[1][1])  

print(total_distance)

29.283943962766887

如何使用 reduce 函数计算距离,而不是使用 pandas.DataFrame.iterrows

首先,您可以使用 shift:

以矢量化方式计算距离
df['dist'] = np.sqrt((df['x']-df['x'].shift(-1))**2 + (df['y']-df['y'].shift(-1))**2)

然后你可以创建一个掩码来满足 True 条件,在列标志上使用 cumsumdiff:

mask_true = df['flag'].cumsum().diff().fillna(df['flag']).gt(0)
# now use loc to select these rows and the dist column plus sum
print (df.loc[mask_true,'dist'].sum())
# 29.283943962766887

对于 False 条件,那么我猜它是互补的,所以你得到:

print (df.loc[~mask_true,'dist'].sum())
# 20.39834563766817

编辑:有时,最简单的解决方案不会排在第一位,但实际上,mask_truedf['flag'] 所以一旦你创建了 dist 列,你可以直接执行:

print (df.loc[df['flag'],'dist'].sum())
# 29.283943962766887
print (df.loc[~df['flag'],'dist'].sum())
# 20.39834563766817