如何使用 pandas 计算过去 24 小时内的滚动累积非重复计数?

问题描述 投票:0回答:1

我有一个交易数据,包含三列,分别包括 user_account、transaction_id 和 transaction_date。我想根据 user_account 和 24 小时时间段计算不同 transaction_id 的滚动累积计数。下面显示了一个示例。

数据 |用户帐户 | transaction_date |transaction_id |cumulative_distinct_count | -------- | -------- | -------- | -------- | | X0119989 | 2024-04-03 14:03:46| G0000006 |1 | | X0119989 | 2024-04-22 22:35:16| G0000005 |1 | | X0119989 | 2024-04-22 22:56:43| G0000004 |2 | | X0119989 | 2024-04-25 20:24:36| G0000003 |1 | | X0119989 | 2024-04-25 21:02:54| G0000002 |2 | | X0119989 | 2024-04-25 21:52:13| G0000001 |3 | | X0119999 | 2024-04-01 22:44:05| G0000012 |1 | | X0119999 | 2024-04-01 22:46:00| G0000011 |2 | | X0119999 | 2024-04-01 22:54:21| G0000010 |3 | | X0119999 | 2024-04-01 22:59:33| G0000009 |4 | | X0119999 | 2024-04-01 23:07:46| G0000008 |5 | | X0119999 | 2024-04-02 00:02:20| G0000007 |6 |

上表中,第一行的事务id“G0000006”在“cumulative_distinct_count”列中为1,是因为在“2024/4/3 14:03”的过去24小时内除了其本身之外没有其他事务id发生:46"。第三行的交易id“G0000004”有2,因为在“2024/4/22 22:56:43”的过去24小时内有两笔交易,包括“G0000004”和“G0000005”发生了。我想做的是计算列“cumulative_distinct_count”。

我目前使用 pandas 的 apply 方法找到了一个不需要的解决方案。代码如下所示。

def count_unique_id(x):
    condition = (data['datetime'].between(x['datetime'] - dt.timedelta(days=1), x['datetime'])) & (data['user_account'] == x['user_account'])
    return g[condition]['transaction_id'].nunique()


g['count_unique_id'] = g.swifter.apply(count_unique_id, axis=1)

由于数据量超过 300 万行,上述解决方案对我来说花费了太多时间。我正在寻找其他可以运行得更快的解决方案。

提前致谢。

pandas group-by apply timedelta cumsum
1个回答
0
投票

一种方法如下:

import pandas as pd
from datetime import timedelta

data = {
    'user_account': ['user1', 'user1', 'user1', 'user2', 'user2', 'user2'],
    'transaction_id': ['G0000006', 'G0000005', 'G0000004', 'G0000010', 'G0000009', 'G0000008'],
    'transaction_date': [
        '2024/04/03 14:03:46', 
        '2024/04/03 18:20:00', 
        '2024/04/22 22:56:43', 
        '2024/04/22 14:03:46', 
        '2024/04/23 18:20:00', 
        '2024/04/24 22:56:43'
    ]
}

df = pd.DataFrame(data)
df['transaction_date'] = pd.to_datetime(df['transaction_date'])

df = df.sort_values(by=['user_account', 'transaction_date'])

def rolling_distinct_count(group):
    result = []
    for i in range(len(group)):
        start_time = group['transaction_date'].iloc[i] - timedelta(days=1)
        end_time = group['transaction_date'].iloc[i]
        count = group[(group['transaction_date'] > start_time) & (group['transaction_date'] <= end_time)]['transaction_id'].nunique()
        result.append(count)
    return pd.Series(result, index=group.index)

df['cumulative_distinct_count'] = df.groupby('user_account').apply(rolling_distinct_count).reset_index(level=0, drop=True)

print(df)

这给出了


  user_account transaction_id    transaction_date  cumulative_distinct_count
0        user1       G0000006 2024-04-03 14:03:46                          1
1        user1       G0000005 2024-04-03 18:20:00                          2
2        user1       G0000004 2024-04-22 22:56:43                          1
3        user2       G0000010 2024-04-22 14:03:46                          1
4        user2       G0000009 2024-04-23 18:20:00                          1
5        user2       G0000008 2024-04-24 22:56:43                          1
© www.soinside.com 2019 - 2024. All rights reserved.