我有一个 pandas DataFrame 表示具有两列的时间序列:“interaction_type”和“timestamps”。 “interaction_type”列包含分类值(“聊天”、“呼叫”、“电子邮件”等),“时间戳”列包含相应的时间戳。 示例数据:
interaction_type timestamps
1 Chat 2017-05-01 00:00:01
2 Chat 2017-05-01 00:00:04
3 Chat 2017-05-01 00:00:15
4 Chat 2017-05-01 00:00:15
5 Chat 2017-05-01 00:00:21
6 Call 2017-05-01 00:00:24
7 Chat 2017-05-01 00:00:31
8 Email 2017-05-01 00:00:32
我想计算滚动时间窗口(“5s”、“10s”等)内每种客户交互类型(“聊天”、“通话”、“电子邮件”等)的滚动比例,即每种交互类型除以每个时间窗口中的总行数。然后我想在同一个图上根据时间窗口时间戳绘制这些图。
我尝试将时间戳设置为 DataFrame 索引并使用 groupby、重新采样和滚动方法,但无法完全使其正常工作。我正在处理一个巨大的数据集,并且希望坚持矢量化操作并且没有大循环。
pd.date_range
、pd.DataFrame.merge
、pd.DataFrame.value_counts
和 pd.get_dummies(df).rolling
的组合来跨先前每秒按时间戳列出的事件的计数频率分组的窗口应用函数:例如,
在此示例中,我选择了一天中的整个 24 小时(2017 年 5 月 1 日),从所有 86,400 可能的秒中随机采样了 100,000 秒,并将这些秒级精度时间戳随机分配给来自
["chat", "email", "call"]
的抽签。因此,有些秒可能有多个值(即使是相同的交互类型),而有些秒可能随机没有值。因此需要创建一个定期索引的“骨架”数据框以与数据集合并。
import datetime
import random
import numpy as np
import pandas as pd
dates = [
datetime.datetime(
2017,
5,
1,
random.randint(0, 23),
random.randint(0, 59),
random.randint(0, 59),
)
for _ in range(100000)
]
ss = pd.date_range("05/01/2017", periods=86400, freq="s")
skeleton = pd.DataFrame(index=ss)
interactions = ["chat", "email", "call"]
df = pd.DataFrame(
{
"interaction_type": list(random.choices(interactions, k=len(dates))),
"timestamp": dates,
}
)
df = df.merge(skeleton, left_on="timestamp", right_index=True, how="outer")
df.set_index("timestamp", inplace=True)
df.sort_index(inplace=True)
df
这里我使用
pd.value_counts
代替 groupby,并用零填充 NaN。现在我们有了每秒每种交互类型的计数,接下来只需要计算滚动窗口总和即可。
df_agg = (
df.value_counts(["timestamp", "interaction_type"], dropna=False)
.sort_index()
.unstack()
.drop([np.nan], axis=1)
.fillna(0)
)
df_agg
我刚刚意识到在你的问题中你要求的是百分比,所以这需要一点额外的代码。但希望这个示例足够清楚地说明了如何更改下面的代码以在数据帧切片的滚动窗口上执行您想要的任何功能。
df_window_sum = pd.get_dummies(df_agg).rolling('10s').sum()
df_window_sum
import plotly.express as px
df_window_sum.reset_index(inplace=True)
fig = px.line(df_window_sum, x="timestamp", y=interactions)
fig.show()