如何测量事件开始后经过的时间,并将其记录在新的数据框列中?

How to measure the time elapsed since the beginning of an event, and record it in a new dataframe column?

我正在尝试测量自事件开始以来经过的时间。在这种情况下,我想知道每分钟交易的比特币数量是否超过了某个阈值。因为推动价格的是成交量。所以我想测量有多久的显着体积,并在新列中记录此测量值。

这是一个数据框示例,其中包含索引中的日期、比特币价格和交易量。我添加了一个列,指示音量何时超过某个阈值:

df = pd.DataFrame({
    'Time': ['2022-01-11 09:30:00', '2022-01-11 09:31:00', '2022-01-11 09:32:00', '2022-01-11 09:33:00', '2022-01-11 09:34:00', '2022-01-11 09:35:00', ],
    'Volume': ['132', '109', '74', '57', '123', '21'],
    'Volume_cat': ["big_volume", "big_volume", None, None, "big_volume", None],
})

df['Time'] = pd.to_datetime(df['Time'])
df.set_index(['Time'], inplace =True)
df

我的目标是拥有一个新列,显示自上次检测到 'big_volume' 事件以来经过的时间(以秒为单位),并在每次新检测时重置自身。 这是可以添加到示例代码中的一行:

df['delta_big_vol'] = ['60', '120', '180', '240', '60', '120',]
df

我必须使用 apply() 方法,但尚未找到任何可用的 lambda。 在伪代码中它看起来像:

from datetime import timedelta
df['delta_xl_vol'] = df.apply(if df["Volume"] > 100 : return(timedelta.total_seconds))

感谢您的帮助。

对于这个过程,我们的“Volume_cat”列中不能有空值:

>>> df["Volume_cat"] = df["Volume_cat"].fillna("-")  # This could be any string except "big_volume"

这一步对我们以后有帮助。我们会记住我们的数据是否以 "big_volume" 开头,并且还会存储第一个“big_volume”行的索引。

>>> idx_of_first_big_volume = df.loc[df["Volume_cat"] == "big_volume"].head(1).index[0]
>>> starts_with_big_volume = idx_of_first_big_volume == df.index[0]

现在,让我们为“Volume_cat”列中的每组连续值分配一个组(连续的“big_volume”被分组,连续的“-”也被分组)。

>>> df["Group"] = ((df.Volume_cat != df.Volume_cat.shift()).cumsum())

然后,我们将对每个组进行排名。现在重要的是对连续的组进行分组,从“big_volume”组开始,然后是“-”组,分配从最早的“big_volume”事件到最后一个 [=34] 的排名=]-"big_volume" 事件(我希望这是有道理的)。另外,请注意 starts_with_big_volume 如何帮助我们正确对齐组。如果我们从 "big_volume" 组开始,我们需要通过减去 1:

来移动值
>>> df["rank"] = df.groupby((df["Group"] - 1 * starts_with_big_volume)// 2)["Volume_cat"].rank("first", ascending=False)

最后,我们可以使用我们的“排名”列并将其乘以 60 以获得自最后一行“big_volume”观察以来的秒数。您可以在数据框的副本中执行此操作,然后在原始数据框中包含“delta_big_vol”列,因为输出中有所有这些新列。

>>> df["delta_big_vol"] = 60 * (df["rank"] - 1)

此外,我们现在可以使用我们的 idx_of_first_big_volume 来满足您在第一个“big_volume”事件之前用 None 填充所有观察值的要求:

>>> df.loc[:idx_of_first_big_volume, "delta_big_vol"].iloc[:-1] = None

这应该是您得到的输出:

>>> df
                    Volume  Volume_cat  Group  rank  delta_big_vol
Time                                                              
2022-01-11 09:30:00    132  big_volume      1   1.0            0.0
2022-01-11 09:31:00    109  big_volume      1   2.0           60.0
2022-01-11 09:32:00     74           -      2   3.0          120.0
2022-01-11 09:33:00     57           -      2   4.0          180.0
2022-01-11 09:34:00    123  big_volume      3   1.0            0.0
2022-01-11 09:35:00     21           -      4   2.0           60.0

假设 Volume 列包含数值数据(您的列包含 str 数据),您可以

threshold = 100
df['Result'] = (
    df.assign(Result=60).Result
      .groupby((df.Volume > threshold).cumsum()).cumsum()
)

结果

                     Volume  Volume_cat  Result
Time                                           
2022-01-11 09:30:00     132  big_volume      60
2022-01-11 09:31:00     109  big_volume      60
2022-01-11 09:32:00      74        None     120
2022-01-11 09:33:00      57        None     180
2022-01-11 09:34:00     123  big_volume      60
2022-01-11 09:35:00      21        None     120

或者,如果您希望从 0 开始,您可以

df['Result'] = (
    df.assign(Result=(df.Volume <= threshold) * 60).Result
      .groupby((df.Volume > threshold).cumsum()).cumsum()
)

结果

                     Volume  Volume_cat  Result
Time                                           
2022-01-11 09:30:00     132  big_volume       0
2022-01-11 09:31:00     109  big_volume       0
2022-01-11 09:32:00      74        None      60
2022-01-11 09:33:00      57        None     120
2022-01-11 09:34:00     123  big_volume       0
2022-01-11 09:35:00      21        None      60

编辑 重新评论:我不是很确定,我理解正确。

你可以试试:

threshold = 100
mask = df.Volume > threshold
idx_min = df.index[mask][0]
mask &= ~mask.shift().fillna(False)
df['Result'] = (~mask) * 60
df['Result'] = df.Result.groupby(mask.cumsum()).cumsum().loc[idx_min:]

修改后的样本框的结果

                     Volume
Time                       
2022-01-11 09:30:00      99
2022-01-11 09:31:00     109
2022-01-11 09:32:00     101
2022-01-11 09:33:00      57
2022-01-11 09:34:00     123
2022-01-11 09:35:00      21

                     Volume  Result
Time                               
2022-01-11 09:30:00      99     NaN
2022-01-11 09:31:00     109     0.0
2022-01-11 09:32:00     101    60.0
2022-01-11 09:33:00      57   120.0
2022-01-11 09:34:00     123     0.0
2022-01-11 09:35:00      21    60.0