【问题标题】:Dynamically change row index in loc method of pandas在熊猫的loc方法中动态更改行索引
【发布时间】:2021-02-19 21:17:26
【问题描述】:

我有一个名为 idx 的 DatetimeIndex:

DatetimeIndex(['2020-10-24 21:00:00+03:00', '2020-10-24 23:00:00+03:00',
           '2020-10-25 08:00:00+03:00', '2020-10-26 08:00:00+03:00',
           '2020-10-27 13:00:00+03:00', '2020-10-29 07:00:00+03:00',
           '2020-10-29 22:00:00+03:00', '2020-10-31 01:00:00+03:00',
           '2020-11-01 16:00:00+03:00', '2020-11-03 18:00:00+03:00',
           '2020-11-04 20:00:00+03:00', '2020-11-05 17:00:00+03:00'],
          dtype='datetime64[ns, Europe/Moscow]', freq=None)

我需要遍历数据框行以计算每个行的“关闭”列的累积最大值 idx 元素到下一个,然后从下一个到下一个,依此类推。 这样做效果很好:

for i in np.arange(len(idx)):
    signals.loc[idx[i]:, 'close_max'] = signals.loc[idx[i]:, 'close'].cummax(axis=0)

但迭代数据框并不是一件好事。你能在没有 for 循环的情况下帮忙吗?

【问题讨论】:

  • 我不太明白您想做什么,但您认为可以并行执行还是需要为每一行生成额外数据?
  • @Charalamm 我需要为来自 idx 的时间戳之间的每个间隔找到“关闭”列的最大值
  • 还是没完全明白,抱歉。你试过.apply()吗?它在整列中应用括号内的函数

标签: python pandas for-loop iteration pandas-loc


【解决方案1】:

您可以使用np.searchsorted 找到您的idx 值在df.index 内的整数索引(奖励:即使在df.index 中找不到idx 的值,它也可以工作)。

一旦你有了这些整数索引,建立一个grp 值适合你的 df 分组。然后groupby 并申请cummax

把它们放在一起:

ix = np.concatenate(([0], np.searchsorted(df.index, idx), [df.shape[0]]))
grp = np.repeat(ix[:-1], np.diff(ix))
df['close_max'] = df['close'].groupby(grp).cummax()

验证:

首先,让我们构建一些类似于您的数据,用于测试:

n = 1000
df = pd.DataFrame(
    420 + np.round(np.cumsum(np.random.normal(size=n)), 2),
    columns=['close'],
    index=pd.date_range('2020-10-24', periods=n, freq='h'))

idx = [
    pd.Timestamp('2020-10-24') + k * pd.Timedelta('1 hour')
    for k in np.cumsum(np.random.randint(1, 48, size=n))
]
idx =[t for t in idx if df.first_valid_index() <= t <= df.last_valid_index()]
idx = pd.DatetimeIndex(idx)

然后,您的“信号”计算稍作修改,以便没有 NaN:

signals = df[['close']].copy()
signals['close_max'] = signals['close'].cummax()
for t in idx:
    signals.loc[t:, 'close_max'] = signals.loc[t:, 'close'].cummax()

# apply the three lines in the solution above to add 'close_max' to df
# and finally:

signals.equals(df)
# True

【讨论】:

  • 谢谢!它工作得很好,比 for 循环快四倍。
猜你喜欢
  • 1970-01-01
  • 2013-01-12
  • 2021-08-31
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
  • 2021-02-07
  • 2016-09-10
  • 2020-04-01
相关资源
最近更新 更多