首页 > 解决方案 > Pandas:计算过去 48 小时内每个帐户看到的设备数量

问题描述

使用 Python 的 Pandas API,对于每个时间戳,我想根据每个时间戳计算过去 48 小时内帐户中唯一设备的数量。

这是我的数据的样子:

╔═════════════════════╦══════════╦═══════════╗
║      timestamp      ║  device  ║ accountid ║
╠═════════════════════╬══════════╬═══════════╣
║ 2018-10-29 18:52:30 ║ d1ed6e6  ║ DhHUXPw   ║
║ 2018-11-01 18:52:30 ║ d123ff96 ║ zgffRDY   ║
║ 2018-11-01 20:53:30 ║ e322ff96 ║ zgffRDY   ║
║ 2018-11-02 21:33:30 ║ g133gf42 ║ zgffRDY   ║
║ 2018-11-15 18:52:30 ║ d123ff96 ║ awfdsct   ║
║ 2018-11-17 08:25:30 ║ d123ff96 ║ awfdsct   ║
╚═════════════════════╩══════════╩═══════════╝

我除了输出看起来像这样。本质上,对于帐户zgffRDYat 2018-11-02 21:33:30,我们3在过去 48 小时内看到了唯一的设备,而在2018-11-01 18:52:30,我们只看到1了设备(当前设备)

╔═════════════════════╦══════════╦═══════════╦═══════════════════════════╗
║      timestamp      ║  device  ║ accountid ║ last_48hour_device_count  ║
╠═════════════════════╬══════════╬═══════════╬═══════════════════════════╣
║ 2018-10-29 18:52:30 ║ d1ed6e6  ║ DhHUXPw   ║                         1 ║
║ 2018-11-01 18:52:30 ║ d123ff96 ║ zgffRDY   ║                         1 ║
║ 2018-11-01 20:53:30 ║ e322ff96 ║ zgffRDY   ║                         2 ║
║ 2018-11-02 21:33:30 ║ g133gf42 ║ zgffRDY   ║                         3 ║
║ 2018-11-15 18:52:30 ║ d123ff96 ║ awfdsct   ║                         1 ║
║ 2018-11-16 08:25:30 ║ d123ff96 ║ awfdsct   ║                         1 ║
╚═════════════════════╩══════════╩═══════════╩═══════════════════════════╝

我当前的代码如下所示。

count_list = []

for idx, row in df.iterrows():
    account = row['accountid']
    earliest = row['timestamp'] - pd.to_timedelta('48 hours')
    current_time = row['timestamp']

    filtered_data = df.query('timestamp >= @earliest and '
                                    'timestamp < @current_time and '
                                    'accountid == @account')

    device_cnt = len(set(filtered_data['device']))
    count_list.append(device_cnt)

df['last_48hour_device_count'] = count_list

我得到了正确的输出,但是我的代码运行得太慢了,而且我有一个包含大量观察结果的数据集。

你知道解决这个问题的更好方法吗?

标签: pythonpandasfilteraggregate

解决方案


您专注于帐户 ID,所以我的建议是首先到groupbyaccountid领域。

添加设备 id 字段后,这与此SO 问题非常相似。所以我认为你的最终结果如下:

cutoff = pd.Timestamp.now() - pd.to_timedelta('48 hours')
df = df[timestamp > cutoff]
df.groupby('accountid').device.nunique()

推荐阅读