假设你有一个
DataFrame
有 n 行,在这种情况下有 3 行:
High Low
0 100 90
1 110 95
2 105 80
我想计算一行与后续行之间的最大差异,如下所示。
因此,例如,第一个计算是第一行的最高价,减去所有行的最低价:100 - 90、100 - 95 和 100 - 80。这些差异中最大的是 20。移动到下一行,110 - 95、110 - 80。这些差异中最大的是 30。转到最后一行,105 - 80 = 25。所有差异中最大的是 30,所以我想返回元组 (110, 80) ,或等价地,其中
loc
的DataFrame
是,(1, 2)
我知道我可以用两个
for loop
。是否有pythonic
或pandas-onic
,我猜functional
方法来做到这一点?
不是最漂亮的解决方案,但您可以利用
:=
运算符:
_, h, l, idx_high, idx_low = max(
(
(
idxm:=((h:=df.at[i, "High"]) - (d2:=df.loc[i:, "Low"])).idxmax(),
h,
d2[idxm],
i,
idxm
)
for i in df.index
),
key=lambda x: x[1] - x[2],
)
print(h, l, idx_high, idx_low)
印花:
110 80 1 2
如果将查找范围的起点和终点的步骤分开,这个问题会更容易。您可以通过执行以下操作来避免在数据帧上进行嵌套循环来计算它:
cummin()
一样,只是cummin()
在数组中向前移动,而我们希望它向后移动。因此,在应用 cummin()
.lowest_future_value = df['Low'][::-1].cummin()[::-1]
hi_start = (df['High'] - lowest_future_value).argmax()
lo_end = df['Low'].iloc[hi_start:].argmin() + hi_start
hi_start, lo_end
这个解决方案在 O(N) 时间内工作,而使用嵌套循环的解决方案需要 O(N^2) 时间。
编辑:这是
df['Low'][::-1].cummin()[::-1]
步骤的替代实现,它跟踪每个值来自的索引。
def backwards_cummin_with_index(series):
smallest = None
smallest_idx = None
ret = []
for i, s in reversed(list(series.items())):
if smallest is None or s < smallest:
smallest = s
smallest_idx = i
ret.append((smallest, smallest_idx))
return reversed(ret)
我会使用 numpy 广播和
np.triu
只得到相关的组合:
a = np.triu(df['High'].to_numpy()[:, None]-df['Low'].to_numpy())
idx = np.unravel_index(a.argmax(), a.shape)
# (1, 2)
values = df.loc[df.index[idx[0]], 'High'], df.loc[df.index[idx[1]], 'Low']
# (110, 80)
中级
a
,只有上三角是相关的:
array([[10, 5, 20],
[ 0, 15, 30],
[ 0, 0, 25]])