我有一个这样的用户表,
USERID Week_Number Year
0 fb 5.0 2021
1 twitter 1.0 2021
2 twitter 2.0 2021
3 twitter 3.0 2021
4 twitter 1.0 2022
5 twitter 2.0 2022
6 twitter 3.0 2022
7 twitter 15.0 2022
8 twitter NaN NaN
9 human 21.0 2022
我想找到在同一年连续3周登录>=的用户。每一年的周数都是独一无二的。例如,在上表中,我们可以看到用户twitter登录在2022年的week_no: 1,2,3中,从而满足了我正在寻找的条件。
我想要的输出,
USERID Year
twitter 2021
twitter 2022
您可以使用
import pandas as pd
import numpy as np
data = pd.DataFrame({"USERID": ["fb", "twitter", "twitter", "twitter", "twitter", "twitter", "twitter", "twitter", "twitter", "human"],
"Week_Number": [5, 1, 2, 3, 1, 2, 3, 15, np.nan, 21],
"Year": ["2021", "2021","2021","2021", "2022", "2022", "2022", "2022", np.nan, "2022"]})
有人能帮我实现这个要求的输出吗?我试过很少的东西,但无法得到适当的输出。
for ix, group in data.groupby([data.USERID, data.Year]):
group = group.sort_values("Week_Number")
group["Diff"] = (group.Week_Number - group.Week_Number.shift(1)).fillna(1)
break
谢谢你提前提供帮助。
发布于 2022-11-16 11:12:29
由于您对至少三个星期的运行(开始或结束)的详细信息不感兴趣,而只对用户连续使用至少三个星期的元组(user, year)
感兴趣,所以非常简单:
def min_consecutive(w, minimum_run=3):
dy = w.diff() != 1
runlen = dy.groupby(dy.cumsum()).size()
return (runlen >= minimum_run).any()
s = (
data
.sort_values('Week_Number')
.groupby(['USERID', 'Year'])['Week_Number']
.apply(min_consecutive)
)
>>> s[s]
USERID Year
twitter 2021 True
2022 True
Name: Week_Number, dtype: bool
解释
我们考虑每一组(user, year)
。在这组中,我们观察到一个(有序的,没有重复的)周数序列。这可以是[1,2,3,12,13,18,19,20,21]
(运行3,运行2,运行4)。系列dy
显示了运行中存在的空白(例如,上面假设的值:[T,F,F,T,F,T,F,F,F]
)。我们使用它的.cumsum()
使每个组连续运行,例如[1,1,1,2,2,3,3,3,3]
。我们取每个组的size
(例如[3,2,4]
),并返回True
当且仅当其中任何一个都是minimum_run
长的。
增编:查找符合标准的周数
以下是一些想法,取决于您希望如何输出。
df = data.dropna().sort_values(['USERID', 'Year', 'Week_Number'])
df = df.assign(rungrp=(df.groupby(['USERID', 'Year'])['Week_Number'].diff() != 1).cumsum())
df = df.loc[df.groupby('rungrp')['rungrp'].transform('count') >= 3]
>>> df
USERID Week_Number Year rungrp
1 twitter 1.0 2021 3
2 twitter 2.0 2021 3
3 twitter 3.0 2021 3
4 twitter 1.0 2022 4
5 twitter 2.0 2022 4
6 twitter 3.0 2022 4
所有这几个星期都是至少3周的一部分。
分组以查找每一次运行的周、分钟和最大值:
>>> df.groupby(['USERID', 'Year', 'rungrp'])['Week_Number'].agg([min, max])
min max
USERID Year rungrp
twitter 2021 3 1.0 3.0
2022 4 1.0 3.0
发布于 2022-11-16 08:55:58
与循环不同,您可以创建一个列,该列将显示用户在一年中是否已连续增长,然后检查该列在一年中是否每个用户超过3:
data.sort_values(by=['USERID','Year','Week_Number'],ascending=True,inplace=True)
data.assign(
grouped_increase = data.groupby([data.USERID, data.Year])["Week_Number"]
.diff()
.gt(0)
.astype(int)
).groupby([data.USERID, data.Year])["grouped_increase"].sum().reset_index().query(
"grouped_increase >= 3"
).drop(
"grouped_increase", axis=1
)
USERID Year
3 twitter 2022
基于您的评论,使用此DF
USERID Week_Number Year
8 fb 2.0 2021.0
9 fb 3.0 2021.0
10 fb 4.0 2021.0
0 fb 5.0 2021.0
11 fb 2.0 2022.0
12 fb 3.0 2022.0
13 fb 4.0 2022.0
14 fb 5.0 2022.0
7 human 21.0 2022.0
1 twitter 1.0 2021.0
2 twitter 1.0 2022.0
3 twitter 2.0 2022.0
4 twitter 3.0 2022.0
5 twitter 15.0 2022.0
6 twitter NaN NaN
运行上述代码将提供:
USERID Year
0 fb 2021.0
1 fb 2022.0
4 twitter 2022.0
https://stackoverflow.com/questions/74464008
复制相似问题