Python 根据另一列中的条件进行分组

Python 根据另一列中的条件进行分组,python,pandas,numpy,dataframe,pandas-groupby,Python,Pandas,Numpy,Dataframe,Pandas Groupby,我有一个df,如下面的示例,我希望识别在给定时间段内发送相同文本的用户,如一个选项是使用groupby按时间顺序查找下一条匹配的消息,将其合并到原始数据帧,然后过滤到消息间隔

我有一个df,如下面的示例,我希望识别在给定时间段内发送相同文本的用户,如一个选项是使用
groupby
按时间顺序查找下一条匹配的消息,
将其合并到原始数据帧,然后过滤到消息间隔<1小时的地方:

In [402]: df2 = df.merge(df.sort_values("time").groupby("message").shift(), left_index=True, right_index=True, suffixes=["_source", "_target"])

In [403]: df2.loc[df2['time_source'].sub(df2['time_target']).lt("1h"), ["message", "userid_source", "userid_target"]].astype('O')
Out[403]:
   message  userid_source  userid_target
0    hello              1              2
1    hello              2              6
4  not now              5              4

请注意,在您当前的数据中,2和6条消息相隔30分钟,也出现在此处。

一个选项是使用
groupby
按时间顺序查找下一条匹配消息,
将其合并到原始数据框中,然后过滤到消息间隔<1小时的内容:

In [402]: df2 = df.merge(df.sort_values("time").groupby("message").shift(), left_index=True, right_index=True, suffixes=["_source", "_target"])

In [403]: df2.loc[df2['time_source'].sub(df2['time_target']).lt("1h"), ["message", "userid_source", "userid_target"]].astype('O')
Out[403]:
   message  userid_source  userid_target
0    hello              1              2
1    hello              2              6
4  not now              5              4

请注意,在您当前的数据中,2和6条消息相隔30分钟发送给
hello
30分钟,也出现在此处。

不确定这是最优雅的解决方案-但这里有一个使用
分组方式和
滚动方式的解决方案。这种方法的优点是,它可以用于大数据集。它不会创建发送相同消息的所有用户和时间的完整笛卡尔积

res = [] 

def collect_users(x):
    if len(x) > 1: 
        s = set(x) 
        if res and res[-1].issubset(s):
            res.pop()

        res.append(set(x))
    return 0 

df.groupby("message").rolling("3600s").agg(collect_users)
结果以集合列表的形式出现:

[{1.0, 2.0, 6.0}, {4.0, 5.0}]

不确定它是否是最优雅的解决方案-但这里有一个使用
分组方式
滚动方式
的解决方案。这种方法的优点是,它可以用于大数据集。它不会创建发送相同消息的所有用户和时间的完整笛卡尔积

res = [] 

def collect_users(x):
    if len(x) > 1: 
        s = set(x) 
        if res and res[-1].issubset(s):
            res.pop()

        res.append(set(x))
    return 0 

df.groupby("message").rolling("3600s").agg(collect_users)
结果以集合列表的形式出现:

[{1.0, 2.0, 6.0}, {4.0, 5.0}]

您能提供预期的输出吗?另外,当您说“在60分钟内”时,它是否必须在同一小时内(例如12:15和12:45),或者它是否也指12:45和13:15?(少于60分钟,但时间不同)。条件groupby的输出将是每个文本,其中包含在60分钟内发送该文本的用户ID列表。这是两条消息之间的差异,所以跨小时发送是可以的。您能提供预期的输出吗?此外,当您说“在60分钟内”时,它是否必须在同一小时内(例如12:15和12:45),或者它是否也指12:45和13:15?(少于60分钟,但时间不同)。条件groupby的输出将是每个文本,其中包含在60分钟内发送该文本的用户ID列表。这是两条消息之间的区别,所以跨越几个小时就可以了。谢谢你的回复,这看起来很棒,我喜欢这个逻辑。它似乎在我的一部分数据上运行良好,因此我将看到它在整个集合中的运行情况。再次感谢!谢谢你的回复,这看起来很棒,我喜欢这个逻辑。它似乎在我的一部分数据上运行良好,因此我将看到它在整个集合中的运行情况。再次感谢!