在 groupby 数据帧上使用滚动时间段 window 计算
Using rolling time period window calculations on a groupby dataframe
这是我当前的Dataframe,按登录时间排序的csv文件,然后reset_index
Login Time User Port
0 2019-10-19 22:00:05 Jane 22
1 2019-10-19 22:00:05 Jane 22
2 2019-10-19 22:02:30 John 22
3 2019-10-19 22:02:44 John 22
4 2019-10-19 22:02:54 John 22
5 2019-10-19 22:03:59 Mary 22
6 2019-10-19 22:04:12 John 22
7 2019-10-19 22:04:17 John 22
8 2019-10-19 22:04:42 Kathy 22
9 2019-10-19 22:04:42 Kathy 22
我想要的是一个单独的列,用于计算用户在过去 30 秒内登录的次数,如下所示:
Login Time User Port LastLogin30Sec
0 2019-10-19 22:00:05 Jane 22 1
1 2019-10-19 22:00:05 Jane 22 2
2 2019-10-19 22:02:30 John 22 1
3 2019-10-19 22:02:44 John 22 2
4 2019-10-19 22:02:54 John 22 3
5 2019-10-19 22:03:59 Mary 22 1
6 2019-10-19 22:04:12 John 22 1
7 2019-10-19 22:04:17 John 22 2
8 2019-10-19 22:04:42 Kathy 22 1
9 2019-10-19 22:04:42 Kathy 22 2
所以我决定使用滚动来指定时间段并计算行数。滚动时间段需要索引 DateTime
df = df.set_index("Login Time")
df[df["User"]=="John"]["Port"].rolling("30s").count()
Login Time
2019-10-19 22:02:30 1.0
2019-10-19 22:02:44 2.0
2019-10-19 22:02:54 3.0
2019-10-19 22:04:12 1.0
2019-10-19 22:04:17 2.0
Name: Port, dtype: float64
好的,代码有效。但我想为每个用户都这样做,所以我决定利用 groupby ......这就是遇到绊脚石的地方。
因为按时间段滚动需要日期时间索引,所以我必须在 groupby 中保留索引。但是非唯一的索引
df["Count"] = df.groupby(["User"], as_index=False)['Port'].rolling("30s").count()
ValueError: cannot handle a non-unique multi-index!
所以我想,我最好不要首先设置时间索引,然后在 groupby 操作之后设置它....但是你不能 set_index 在 groupbydataframe
df["Count"] = df.groupby(["User"], as_index=False).set_index("Login Time")["Port"].rolling("30s").count()
AttributeError: Cannot access callable attribute 'set_index' of 'DataFrameGroupBy' objects, try using the 'apply' method
而且我不知道 apply 对我有什么用。
有谁能提供进一步的建议吗?整个问题似乎围绕着 .rolling time window 需要一个 datetimeindex 而不仅仅是一个 datetime 系列
您可以使用应用功能,您可以在其中为每个组执行滚动功能
df = pd.DataFrame([[0, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [1, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [2, pd.Timestamp('2019-10-19 22:02:30'), 'John', '22'], [3, pd.Timestamp('2019-10-19 22:02:44'), 'John', '22'], [4, pd.Timestamp('2019-10-19 22:02:54'), 'John', '22'], [5, pd.Timestamp('2019-10-19 22:03:59'), 'Mary', '22'], [6, pd.Timestamp('2019-10-19 22:04:12'), 'John', '22'], [7, pd.Timestamp('2019-10-19 22:04:17'), 'John', '22'], [8, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22'], [9, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22']], columns=('id', 'Login-Time', 'User', 'Port'))
df2 = df.groupby("User").apply(lambda g: g.set_index("Login-Time")["Port"].rolling("30s").count()).reset_index()
print(df2)
结果
User Login-Time Port
0 Jane 2019-10-19 22:00:05 1.0
1 Jane 2019-10-19 22:00:05 2.0
2 John 2019-10-19 22:02:30 1.0
3 John 2019-10-19 22:02:44 2.0
4 John 2019-10-19 22:02:54 3.0
5 John 2019-10-19 22:04:12 1.0
6 John 2019-10-19 22:04:17 2.0
7 Kathy 2019-10-19 22:04:42 1.0
8 Kathy 2019-10-19 22:04:42 2.0
9 Mary 2019-10-19 22:03:59 1.0
这是我当前的Dataframe,按登录时间排序的csv文件,然后reset_index
Login Time User Port
0 2019-10-19 22:00:05 Jane 22
1 2019-10-19 22:00:05 Jane 22
2 2019-10-19 22:02:30 John 22
3 2019-10-19 22:02:44 John 22
4 2019-10-19 22:02:54 John 22
5 2019-10-19 22:03:59 Mary 22
6 2019-10-19 22:04:12 John 22
7 2019-10-19 22:04:17 John 22
8 2019-10-19 22:04:42 Kathy 22
9 2019-10-19 22:04:42 Kathy 22
我想要的是一个单独的列,用于计算用户在过去 30 秒内登录的次数,如下所示:
Login Time User Port LastLogin30Sec
0 2019-10-19 22:00:05 Jane 22 1
1 2019-10-19 22:00:05 Jane 22 2
2 2019-10-19 22:02:30 John 22 1
3 2019-10-19 22:02:44 John 22 2
4 2019-10-19 22:02:54 John 22 3
5 2019-10-19 22:03:59 Mary 22 1
6 2019-10-19 22:04:12 John 22 1
7 2019-10-19 22:04:17 John 22 2
8 2019-10-19 22:04:42 Kathy 22 1
9 2019-10-19 22:04:42 Kathy 22 2
所以我决定使用滚动来指定时间段并计算行数。滚动时间段需要索引 DateTime
df = df.set_index("Login Time")
df[df["User"]=="John"]["Port"].rolling("30s").count()
Login Time
2019-10-19 22:02:30 1.0
2019-10-19 22:02:44 2.0
2019-10-19 22:02:54 3.0
2019-10-19 22:04:12 1.0
2019-10-19 22:04:17 2.0
Name: Port, dtype: float64
好的,代码有效。但我想为每个用户都这样做,所以我决定利用 groupby ......这就是遇到绊脚石的地方。
因为按时间段滚动需要日期时间索引,所以我必须在 groupby 中保留索引。但是非唯一的索引
df["Count"] = df.groupby(["User"], as_index=False)['Port'].rolling("30s").count()
ValueError: cannot handle a non-unique multi-index!
所以我想,我最好不要首先设置时间索引,然后在 groupby 操作之后设置它....但是你不能 set_index 在 groupbydataframe
df["Count"] = df.groupby(["User"], as_index=False).set_index("Login Time")["Port"].rolling("30s").count()
AttributeError: Cannot access callable attribute 'set_index' of 'DataFrameGroupBy' objects, try using the 'apply' method
而且我不知道 apply 对我有什么用。
有谁能提供进一步的建议吗?整个问题似乎围绕着 .rolling time window 需要一个 datetimeindex 而不仅仅是一个 datetime 系列
您可以使用应用功能,您可以在其中为每个组执行滚动功能
df = pd.DataFrame([[0, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [1, pd.Timestamp('2019-10-19 22:00:05'), 'Jane', '22'], [2, pd.Timestamp('2019-10-19 22:02:30'), 'John', '22'], [3, pd.Timestamp('2019-10-19 22:02:44'), 'John', '22'], [4, pd.Timestamp('2019-10-19 22:02:54'), 'John', '22'], [5, pd.Timestamp('2019-10-19 22:03:59'), 'Mary', '22'], [6, pd.Timestamp('2019-10-19 22:04:12'), 'John', '22'], [7, pd.Timestamp('2019-10-19 22:04:17'), 'John', '22'], [8, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22'], [9, pd.Timestamp('2019-10-19 22:04:42'), 'Kathy', '22']], columns=('id', 'Login-Time', 'User', 'Port'))
df2 = df.groupby("User").apply(lambda g: g.set_index("Login-Time")["Port"].rolling("30s").count()).reset_index()
print(df2)
结果
User Login-Time Port
0 Jane 2019-10-19 22:00:05 1.0
1 Jane 2019-10-19 22:00:05 2.0
2 John 2019-10-19 22:02:30 1.0
3 John 2019-10-19 22:02:44 2.0
4 John 2019-10-19 22:02:54 3.0
5 John 2019-10-19 22:04:12 1.0
6 John 2019-10-19 22:04:17 2.0
7 Kathy 2019-10-19 22:04:42 1.0
8 Kathy 2019-10-19 22:04:42 2.0
9 Mary 2019-10-19 22:03:59 1.0