在 pandas 中聚合字符串列及时关闭

Aggregate string column close in time in pandas

提问人:Fabitosh 提问时间:10/28/2023 更新时间:10/28/2023 访问量:65

问:

我正在尝试对消息进行分组,这些消息已在不久后发送。参数定义消息之间的最大持续时间,以便将它们视为块的一部分。如果将消息添加到块中,则会延长时间窗口,以便将更多消息视为块的一部分。

示例输入

日期时间 消息
0 2023-01-01 12:00:00 一个
1 2023-01-01 12:20:00 B
2 2023-01-01 12:30:00 C
3 2023-01-01 12:30:55 D
4 2023-01-01 12:31:20 E
5 2023-01-01 15:00:00 F
6 2023-01-01 15:30:30 G
7 2023-01-01 15:30:55 H

参数设置为 1 分钟的预期输出

日期时间 消息 datetime_last n_block
0 2023-01-01 12:00:00 一个 2023-01-01 12:00:00 1
1 2023-01-01 12:20:00 B 2023-01-01 12:20:00 1
2 2023-01-01 12:30:00 C\nD\nE 2023-01-01 12:31:20 3
3 2023-01-01 15:00:00 F 2023-01-01 15:00:00 1
4 2023-01-01 15:30:30 G\nH 2023-01-01 15:30:55 2

我失败的尝试

我希望通过滚动窗口来实现这一点,该窗口将不断附加消息行。

def join_messages(x):
    return '\n'.join(x)

df.rolling(window='1min', on='datetime').agg({
  'datetime': ['first', 'last'], 
  'message': [join_messages, "count"]}) #Somehow overwrite datetime with the aggregated datetime.first.

两个聚合都因 ValueError: 而失败。invalid on specified as datetime, must be a column (of DataFrame), an Index or None

我没有看到一种干净的方法来在窗口中“访问”。此外,滚动也不适用于字符串。我的印象是,这是一条死胡同,有一种更干净的方法。datetime

输入数据和预期数据的代码段

df = pd.DataFrame({
    'datetime': [pd.Timestamp('2023-01-01 12:00'),
                 pd.Timestamp('2023-01-01 12:20'),
                 pd.Timestamp('2023-01-01 12:30:00'),
                 pd.Timestamp('2023-01-01 12:30:55'),
                 pd.Timestamp('2023-01-01 12:31:20'),
                 pd.Timestamp('2023-01-01 15:00'),
                 pd.Timestamp('2023-01-01 15:30:30'),
                 pd.Timestamp('2023-01-01 15:30:55'),],
    'message': list('ABCDEFGH')})


df_expected = pd.DataFrame({
    'datetime': [pd.Timestamp('2023-01-01 12:00'),
                 pd.Timestamp('2023-01-01 12:20'),
                 pd.Timestamp('2023-01-01 12:30:00'),
                 pd.Timestamp('2023-01-01 15:00'),
                 pd.Timestamp('2023-01-01 15:30:30'),],
    'message': ['A', 'B', 'C\nD\nE', 'F', 'G\nH'],
    'datetime_last': [pd.Timestamp('2023-01-01 12:00'),
                      pd.Timestamp('2023-01-01 12:20'),
                      pd.Timestamp('2023-01-01 12:31:20'),
                      pd.Timestamp('2023-01-01 15:00'),
                      pd.Timestamp('2023-01-01 15:30:55'),],
    'n_block': [1, 1, 3, 1, 2]})
Python pandas 字符串 时间序列

评论


答:

4赞 Shubham Sharma 10/28/2023 #1

比较当前和以前的日期时间值以标记差值大于 1 分钟的行,然后在标志上应用累积总和以区分不同的日期时间块。现在,按这些块对数据帧进行分组并聚合以获得结果

m = df['datetime'].diff() > pd.Timedelta(minutes=1)
df.groupby(m.cumsum(), as_index=False).agg(datetime=('datetime', 'first'),
                                           datetime_last=('datetime', 'last'),
                                           message=('message', '\n'.join),
                                           n_block=('message', 'count'))

             datetime       datetime_last  message  n_block
0 2023-01-01 12:00:00 2023-01-01 12:00:00        A        1
1 2023-01-01 12:20:00 2023-01-01 12:20:00        B        1
2 2023-01-01 12:30:00 2023-01-01 12:31:20  C\nD\nE        3
3 2023-01-01 15:00:00 2023-01-01 15:00:00        F        1
4 2023-01-01 15:30:30 2023-01-01 15:30:55     G\nH        2