在 python 中计算一小时内的不同操作

Count different actions within one hour in python

我开始使用时间序列。我有一个用户向不同的国家/地区进行银行转账,但是 he/she 进行转账的最频繁的国家/地区是 X,但也有向 Y 和 Z 国家/地区的转账。假设:

date                           id       country
2020-01-01T00:00:00.000Z       id_01     X
2020-01-01T00:20:00.000Z       id_02     X
2020-01-01T00:25:00.000Z       id_03     Y
2020-01-01T00:35:00.000Z       id_04     X
2020-01-01T00:45:00.000Z       id_05     Z
2020-01-01T01:00:00.000Z       id_06     X
2020-01-01T10:20:00.000Z       id_07     X
2020-01-01T10:25:00.000Z       id_08     X
2020-01-01T13:00:00.000Z       id_09     X
2020-01-01T18:45:00.000Z       id_10     Z
2020-01-01T18:55:00.000Z       id_11     X

由于最频繁出现的国家是 X,我想迭代地计算一小时内(在整个事件列表中)有多少笔交易是针对不同于 X 的国家完成的。

此特定案例的预期输出格式为:

date                           id        country
2020-01-01T00:25:00.000Z       id_03     Y
2020-01-01T00:45:00.000Z       id_05     Z

2020-01-01T00:00:00.000Z开始,一小时内有两笔Y、Z交易。然后从2020-01-01T00:20:00.000Z开始,一个小时内,有相同的交易,以此类推。那么,从2020-01-01T10:20:00.000Z开始,一小时内,都是X。从2020-01-01T18:45:00.000Z开始,一小时内,只有一个Z。

我正在尝试使用双重 for 循环和 .value_counts(),但我不确定自己在做什么。

你可以试试:

df['date'] = pd.to_datetime(df.date)
(df.country != 'X').groupby(by=df.date.dt.hour).sum()

首先,它将您的日期列转换为日期时间。然后,您测试国家/地区是否为 'X',并按小时分组,并对不同于 'X' 的国家/地区数量求和。组是基于小时,而不是滚动消逝的时间。希望它能解决您的问题!

IIUC,你可以 select 只有行不是 X,然后使用 diff 一次向前和一次向后(前后 1 小时内)并且你想要两个差异中的任何一个低于 1 小时的 Timedelta

#convert to datetime
df['date'] = pd.to_datetime(df['date'])

#mask not X and select only these rows
mX = df['country'].ne('X')
df_ = df[mX].copy()

# mask within an hour before and after 
m1H = (df_['date'].diff().le(pd.Timedelta(hours=1)) | 
        df_['date'].diff(-1).le(pd.Timedelta(hours=1)) )

# selet only the rows meeting criteria on X and 1H
df_ = df_[m1H]
print (df_)
                       date     id country
2 2020-01-01 00:25:00+00:00  id_03       Y
4 2020-01-01 00:45:00+00:00  id_05       Z

您是否考虑过为此使用时间序列数据库?如果您以任意时间间隔进行大量基于事件的聚合,它会让您的生活更轻松。时间序列数据库为您抽象了这一点,因此您只需发送一个查询并将结果输入 pandas。它也会 运行 相当快。

例如,可以在 QuestDB 中使用以下语法完成每小时聚合。

select timestamp, country, count() from yourTable SAMPLE BY 1h

这将 return 这样的结果

| timestamp           | country | count |
| 2020-06-22T00:00:00 | X       | 234   |
| 2020-06-22T00:00:00 | Y       | 493   |
| 2020-06-22T01:00:00 | X       |  12   |
| 2020-06-22T01:00:00 | Y       |  66   |

您可以将其调整为每月或每周或 5 分钟的解决结果,而无需重新编写您的逻辑,您需要做的就是将 1h 更改为 1M7d5m 或将其作为参数传递。

现在,要获得目标交易时间戳前后一小时的结果,您可以在上面添加时间戳间隔搜索。例如,假设您的目标交易发生在 2010-01-01T06:47:00.000000Z,结果搜索将是

select hour, country, count() from yourTable 
where timestamp = '2010-01-01T05:47:00.000000Z;2h' 
sample by 1h; 

如果这对您有用,有一个教程介绍如何在 QuestDB 中 运行 这种类型的查询并将结果输入 pandas here