在选定的行上应用差异以比较来自 math.atan2 的角度
Applying diff on selected rows for comparing angles from math.atan2
我有一个像这样的数据框,想要应用 diff 函数:
test = pd.DataFrame({ 'Observation' : ['0','1','2',
'3','4','5',
'6','7','8'],
'Value' : [30,60,170,-170,-130,-60,-30,10,20]
})
Observation Value
0 30
1 60
2 170
3 -170
4 -130
5 -60
6 -30
7 10
8 20
'Value' 列以度为单位。所以,-170
和 170
之间的差异应该是 20
,而不是 -340
。换句话说,当 d2*d1 < 0
,而不是 d2-d1
,我想得到 360-(abs(d1)+abs(d2))
这就是我尝试的原因。但是后来我不知道如何在不使用 for 循环的情况下继续它:
test['Value_diff_1st_attempt'] = test['Value'].diff(1)
test['sign_temp'] = test['Value'].shift()
test['Sign'] = np.sign(test['Value']*test['sign_temp'])
结果应该是这样的:
Observation Value Delta_Value
0 30 NAN
1 60 30
2 170 110
3 -170 20
4 -130 40
5 -60 70
6 -30 30
7 10 40
8 20 10
最后我想知道所有正值的差异幅度。谢谢。
更新:因此,值结果来自 math.atan2
函数。这些值来自 0<theta<180
或 -180<theta<0
。例如,当我们处理从 170
(左上角)到 -170
(左下角)的方向变化时,问题就出现了,其中变化实际上只是 20
度。但是,当我们从-30
(右下角)到10
(右上角)时,变化真的是40
度。我希望我解释得很好。
我相信这应该有效(采用 @JasonD's answer 的定义):
test["Value"].rolling(2).apply(lambda x: 180 - abs(abs(x[0] - x[1]) - 180))
Out[45]:
0 NaN
1 30.0
2 110.0
3 20.0
4 40.0
5 70.0
6 30.0
7 40.0
8 10.0
Name: Value, dtype: float64
工作原理:
根据你的问题,a和b两个角在0
和+/-180
之间。对于 0 < d < 180
我会写 d < 180
,对于 -180 < d < 0
我会写 d < 0
。有四种可能:
a < 180
, b < 180
-> 结果就是 |a - b|
。由于 |a - b| - 180
不能大于 180,公式将简化为 a - b
if a > b
和 b - a
if b > a
.
a < 0
, b < 0
-> 同样的逻辑也适用于此。负数和它们的绝对差不能大于180。结果将是|a - b|
.
a < 180
,b < 0
->a-b肯定大于0。对于 |a - b| > 180
的情况,我们应该从另一个角度看,这转化为 360 - |a - b|
.
a < 0
, b < 180
-> 同样,与上面类似。如果绝对差值大于 180,则计算 360 - 绝对差值。
对于 pandas 部分:rolling(n)
创建大小为 n 的数组。对于 2:(第 0 行,第 1 行),(第 1 行,第 2 行),... 使用 apply
,您将该公式应用于每个滚动对,其中 x[0]
是第一个元素 (a) 并且 x[1]
是第二个元素。
我有一个像这样的数据框,想要应用 diff 函数:
test = pd.DataFrame({ 'Observation' : ['0','1','2',
'3','4','5',
'6','7','8'],
'Value' : [30,60,170,-170,-130,-60,-30,10,20]
})
Observation Value
0 30
1 60
2 170
3 -170
4 -130
5 -60
6 -30
7 10
8 20
'Value' 列以度为单位。所以,-170
和 170
之间的差异应该是 20
,而不是 -340
。换句话说,当 d2*d1 < 0
,而不是 d2-d1
,我想得到 360-(abs(d1)+abs(d2))
这就是我尝试的原因。但是后来我不知道如何在不使用 for 循环的情况下继续它:
test['Value_diff_1st_attempt'] = test['Value'].diff(1)
test['sign_temp'] = test['Value'].shift()
test['Sign'] = np.sign(test['Value']*test['sign_temp'])
结果应该是这样的:
Observation Value Delta_Value
0 30 NAN
1 60 30
2 170 110
3 -170 20
4 -130 40
5 -60 70
6 -30 30
7 10 40
8 20 10
最后我想知道所有正值的差异幅度。谢谢。
更新:因此,值结果来自 math.atan2
函数。这些值来自 0<theta<180
或 -180<theta<0
。例如,当我们处理从 170
(左上角)到 -170
(左下角)的方向变化时,问题就出现了,其中变化实际上只是 20
度。但是,当我们从-30
(右下角)到10
(右上角)时,变化真的是40
度。我希望我解释得很好。
我相信这应该有效(采用 @JasonD's answer 的定义):
test["Value"].rolling(2).apply(lambda x: 180 - abs(abs(x[0] - x[1]) - 180))
Out[45]:
0 NaN
1 30.0
2 110.0
3 20.0
4 40.0
5 70.0
6 30.0
7 40.0
8 10.0
Name: Value, dtype: float64
工作原理:
根据你的问题,a和b两个角在0
和+/-180
之间。对于 0 < d < 180
我会写 d < 180
,对于 -180 < d < 0
我会写 d < 0
。有四种可能:
a < 180
,b < 180
-> 结果就是|a - b|
。由于|a - b| - 180
不能大于 180,公式将简化为a - b
ifa > b
和b - a
ifb > a
.a < 0
,b < 0
-> 同样的逻辑也适用于此。负数和它们的绝对差不能大于180。结果将是|a - b|
.a < 180
,b < 0
->a-b肯定大于0。对于|a - b| > 180
的情况,我们应该从另一个角度看,这转化为360 - |a - b|
.a < 0
,b < 180
-> 同样,与上面类似。如果绝对差值大于 180,则计算 360 - 绝对差值。
对于 pandas 部分:rolling(n)
创建大小为 n 的数组。对于 2:(第 0 行,第 1 行),(第 1 行,第 2 行),... 使用 apply
,您将该公式应用于每个滚动对,其中 x[0]
是第一个元素 (a) 并且 x[1]
是第二个元素。