[英]How to measure the time elapsed since the beginning of an event, and record it in a new dataframe column?
我正在嘗試測量自事件開始以來經過的時間。 在這種情況下,我想知道每分鍾交易的比特幣數量是否超過了某個閾值。 因為推動價格的是成交量。 因此,我想測量大量交易量持續了多長時間,並將此測量值記錄在一個新列中。
這是一個 dataframe 的示例,其中包含索引中的日期、比特幣價格和交易量。 我添加了一列,指示音量何時超過某個閾值:
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”列中不能有 null 個值:
>>> 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”事件到最后一個非新“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)
最后,我們可以使用我們的“rank”列並將其乘以 60 以獲得自最后一行“big_volume”觀察以來的秒數。 由於 output 中的所有這些新列,您可以在 dataframe 的副本中執行此操作,然后在原始 dataframe 中包含“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
這應該是您得到的 output:
>>> 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.