python - Pandas - 当 N 存储在一列中时,新列基于另一列 N 行的值
问题描述
我有一个带有示例数据的熊猫数据框:
idx price lookback
0 5
1 7 1
2 4 2
3 3 1
4 7 3
5 6 1
回溯可以是正数或负数,但我想取它的绝对值来获取多少行来取值。
我正在尝试创建一个包含price
from lookback + 1
rows ago 的值的新列,例如:
idx price lookback lb_price
0 5 NaN NaN
1 7 1 NaN
2 4 2 NaN
3 3 1 7
4 7 3 5
5 6 1 3
我从感觉最明显的方式开始,这不起作用:
df['sbc'] = df['price'].shift(dataframe['lb'].abs() + 1)
然后我尝试使用 lambda,这没有用,但我可能做错了:
sbc = lambda c, x: pd.Series(zip(*[c.shift(x+1)]))
df['sbc'] = sbc(df['price'], df['lb'].abs())
我还尝试了一个循环(非常慢,但有效),但我确信有更好的方法:
lookback = np.nan
for i in range(len(df)):
if df.loc[i, 'lookback']:
if not np.isnan(df.loc[i, 'lookback']):
lookback = abs(int(df.loc[i, 'lookback']))
if not np.isnan(lookback) and (lookback + 1) < i:
df.loc[i, 'lb_price'] = df.loc[i - (lookback + 1), 'price']
我已经看到了使用lambda
,的示例df.apply
,也许,Series.map
但它们对我来说并不清楚,因为我是 Python 和 Pandas 的新手。
如果有不使用循环的方法,我正在寻找最快的方法。
另外,为了它的价值,我计划使用这个计算列来创建另一个列,我可以这样做:
df['streak-roc'] = 100 * (df['price'] - df['lb_price']) / df['lb_price']
但是,如果我可以将所有这些组合成一种真正有效的方法,那将是理想的。
解决方案!
提供的几个解决方案效果很好(谢谢!)但都需要一些小的调整来处理我的负数潜力,这是一个回顾 + 1 而不是 - 1,所以我觉得在这里发布我的修改是谨慎的。
所有这些都比我的原始循环要快得多,原始循环需要5m 26s来处理我的数据集。
我将我观察到的最快的一个标记为公认的,因为我提高循环的速度是主要目标。
编辑解决方案
从 Manas Sambare - 41 秒
df['lb_price'] = df.apply(
lambda x: df['price'][x.name - (abs(int(x['lookback'])) + 1)]
if not np.isnan(x['lookback']) and x.name >= (abs(int(x['lookback'])) + 1)
else np.nan,
axis=1)
从 mannh - 43 秒
def get_lb_price(row, df):
if not np.isnan(row['lookback']):
lb_idx = row.name - (abs(int(row['lookback'])) + 1)
if lb_idx >= 0:
return df.loc[lb_idx, 'price']
else:
return np.nan
df['lb_price'] = dataframe.apply(get_lb_price, axis=1 ,args=(df,))
从比尔 - 18 秒
lookup_idxs = df.index.values - (abs(df['lookback'].values) + 1)
valid_lookups = lookup_idxs >= 0
df['lb_price'] = np.nan
df.loc[valid_lookups, 'lb_price'] = df['price'].to_numpy()[lookup_idxs[valid_lookups].astype(int)]
解决方案
通过使用 row.name 在 df.apply() 调用中获取行的索引,您可以生成与当前所在行相关的“lb_price”数据。
%time
df.apply(
lambda x: df['price'][x.name - int(x['lookback'] + 1)]
if not np.isnan(x['lookback']) and x.name >= x['lookback'] + 1
else np.nan,
axis=1)
# > CPU times: user 2 µs, sys: 0 ns, total: 2 µs
# > Wall time: 4.05 µs
仅供参考:您的示例中有一个错误,因为 idx[5] 的 lb_price 应该是 3 而不是 7。
推荐阅读
- node.js - Stripe webhook 在 firebase 功能中不起作用
- c# - 根据给定的整数生成连续的 IPv4 地址
- python - 如何在 python 反应计时器中停止“输入垃圾邮件”
- python - 无法识别和操纵本网站的“弹出”建议好吗?
- xml - ODK 创建测试 - 我可以随机排序吗?
- vega-lite - 日期解析以及何时在 Vega Lite 中使用 utc/TimeUnits?
- java - 无法从 Eclipse springboot 应用程序访问 localhost:8080
- r - 解释类似(但不同)指定线性回归模型的标准误差:R
- math - 将直线的起点和终点修剪到它们进入/退出矩形的位置?
- vba - 使用 VBA 访问 Access 中的 ImportTextFile