使用pandas统计开始时间一小时内发生的用户订单,时间间隔不规则
Using pandas to count user orders that happen within the hour from start time with irregular time interval
假设我们有这个
| eventdatetime | orderid | userid |
| 2019-12-27 03:06:50 | 1 | 100 |
| 2019-12-27 04:12:50 | 2 | 20 |
| 2019-12-27 05:06:58 | 3 | 140 |
| 2019-12-29 03:00:10 | 4 | 104 |
我尝试使用滚动分组,例如df.groupby('userid').rolling('1h').orderid.count()
但它不起作用,因为它向后看 1 小时并将其滚动到行中的当前日期时间。如果我使用滚动,它不期待在接下来的1小时内检查是否有订单。
例如如果查看 orderid 2,日期时间是 04:12:50,所以我想计算从这个时间到 05:12:50 的 1 小时内的订单数量。换句话说,计算用户从 04:12:50 到 05:12:50 下的订单数量 - 在本例中是 2,但滚动会给我 1,因为它看起来是从 03:12:50 到 04:12:50。
pandas 中是否有任何函数可以做到这一点,还是我对滚动的理解有误?
编辑 1
最初我以为我可以只使用一些列,但不知何故它不适用于原始列,所以我将所有列都添加到混合中。
我们这里有日期时间索引和 3 个 id 列
| orderid shopid userid
event_time
2019-12-31 13:13:34 | 31468414075366 214432425 1134243
2019-12-31 23:32:03 | 31505523761333 214432425 1134243
2019-12-31 23:45:49 | 31506349293329 214432425 52594422
2019-12-31 23:46:35 | 31506394434087 214432425 52594422
使用Roy2012的解决方案
但是添加了带有 orderid 的连接条件,因为我稍后需要 orderid 而不仅仅是时间
hour_ends = pd.DataFrame({'hour_start': df.index,
'orderid': df.orderid.values
}, index=df.index + datetime.timedelta(hours=1)
t = pd.merge(df, hour_ends, on='orderid', left_index=True, right_index=True, how='outer')
给我
orderid shopid userid event_start
event_time
2019-12-31 13:13:34 | 31468414075366 214432425.0 | 1134243.0 | NaT
2019-12-31 14:13:34 | 31468414075366 NaN | NaN |2019-12-31 13:13:34
2019-12-31 23:32:03 | 31505523761333 214432425.0 | 1134243.0 | NaT
2019-12-31 23:45:49 | 31506349293329 214432425.0 | 52594422.0 | NaT
2019-12-31 23:46:35 | 31506394434087 214432425.0 | 52594422.0 | NaT
2020-01-01 00:32:03 | 31505523761333 NaN | NaN | 2019-12-31 23:32:03
2020-01-01 00:45:49 | 31506349293329 NaN | NaN | 2019-12-31 23:45:49
2020-01-01 00:46:35 | 31506394434087 NaN | NaN | 2019-12-31 23:46:35
然后添加这个以向前滚动
t["rolling_count"] = t.rolling("1h", closed="both").count()["orderid"]
t.reset_index()[['event_start', 'orderid', 'rolling_count']].dropna()
给出的结果不符合
event_start | orderid | rolling_count
2019-12-31 13:13:34 | 31468414075366 | 2.0
2019-12-31 23:32:03 | 31505523761333 | 4.0
2019-12-31 23:45:49 | 31506349293329 | 4.0
2019-12-31 23:46:35 | 31506394434087 | 4.0
我希望结果类似于
event_start | orderid | rolling_count
2019-12-31 13:13:34 | 31468414075366 | 1.0
2019-12-31 23:32:03 | 31505523761333 | 3.0
2019-12-31 23:45:49 | 31506349293329 | 2.0
2019-12-31 23:46:35 | 31506394434087 | 1.0
因为订单ID 31468414075366在13:13的1小时内只有1个订单,31505523761333在23:32到00:32的1小时内共有3个订单,依此类推
这是一个解决方案。它基于在 'real' 行之后一小时添加人工行的想法。我们将 运行 滚动计数,得到结果,然后将它们匹配回原始时间。这是代码,为清楚起见分为几个步骤。
import datetime
# Create a dataframe with 1 hour time windows
hour_ends = pd.DataFrame({"hour_start": df.index},
index = df.index + datetime.timedelta(hours=1))
# merge the original dataframe and the new one.
t = pd.merge(df, hour_ends, left_index=True, right_index=True, how = "outer")
# do the rolling count.
t["rolling_count"] = t.rolling("1h", closed="both").count()["orderid"]
# match the results back to the starting time.
res = t.reset_index()[["hour_start", "rolling_count"]].dropna()
print (res)
结果是:
hour_start rolling_count
1 2019-12-27 03:06:50 1.0
4 2019-12-27 04:12:50 2.0
5 2019-12-27 05:06:58 1.0
7 2019-12-29 03:00:10 1.0
假设我们有这个
| eventdatetime | orderid | userid |
| 2019-12-27 03:06:50 | 1 | 100 |
| 2019-12-27 04:12:50 | 2 | 20 |
| 2019-12-27 05:06:58 | 3 | 140 |
| 2019-12-29 03:00:10 | 4 | 104 |
我尝试使用滚动分组,例如df.groupby('userid').rolling('1h').orderid.count()
但它不起作用,因为它向后看 1 小时并将其滚动到行中的当前日期时间。如果我使用滚动,它不期待在接下来的1小时内检查是否有订单。
例如如果查看 orderid 2,日期时间是 04:12:50,所以我想计算从这个时间到 05:12:50 的 1 小时内的订单数量。换句话说,计算用户从 04:12:50 到 05:12:50 下的订单数量 - 在本例中是 2,但滚动会给我 1,因为它看起来是从 03:12:50 到 04:12:50。
pandas 中是否有任何函数可以做到这一点,还是我对滚动的理解有误?
编辑 1 最初我以为我可以只使用一些列,但不知何故它不适用于原始列,所以我将所有列都添加到混合中。
我们这里有日期时间索引和 3 个 id 列
| orderid shopid userid
event_time
2019-12-31 13:13:34 | 31468414075366 214432425 1134243
2019-12-31 23:32:03 | 31505523761333 214432425 1134243
2019-12-31 23:45:49 | 31506349293329 214432425 52594422
2019-12-31 23:46:35 | 31506394434087 214432425 52594422
使用Roy2012的解决方案 但是添加了带有 orderid 的连接条件,因为我稍后需要 orderid 而不仅仅是时间
hour_ends = pd.DataFrame({'hour_start': df.index,
'orderid': df.orderid.values
}, index=df.index + datetime.timedelta(hours=1)
t = pd.merge(df, hour_ends, on='orderid', left_index=True, right_index=True, how='outer')
给我
orderid shopid userid event_start
event_time
2019-12-31 13:13:34 | 31468414075366 214432425.0 | 1134243.0 | NaT
2019-12-31 14:13:34 | 31468414075366 NaN | NaN |2019-12-31 13:13:34
2019-12-31 23:32:03 | 31505523761333 214432425.0 | 1134243.0 | NaT
2019-12-31 23:45:49 | 31506349293329 214432425.0 | 52594422.0 | NaT
2019-12-31 23:46:35 | 31506394434087 214432425.0 | 52594422.0 | NaT
2020-01-01 00:32:03 | 31505523761333 NaN | NaN | 2019-12-31 23:32:03
2020-01-01 00:45:49 | 31506349293329 NaN | NaN | 2019-12-31 23:45:49
2020-01-01 00:46:35 | 31506394434087 NaN | NaN | 2019-12-31 23:46:35
然后添加这个以向前滚动
t["rolling_count"] = t.rolling("1h", closed="both").count()["orderid"]
t.reset_index()[['event_start', 'orderid', 'rolling_count']].dropna()
给出的结果不符合
event_start | orderid | rolling_count
2019-12-31 13:13:34 | 31468414075366 | 2.0
2019-12-31 23:32:03 | 31505523761333 | 4.0
2019-12-31 23:45:49 | 31506349293329 | 4.0
2019-12-31 23:46:35 | 31506394434087 | 4.0
我希望结果类似于
event_start | orderid | rolling_count
2019-12-31 13:13:34 | 31468414075366 | 1.0
2019-12-31 23:32:03 | 31505523761333 | 3.0
2019-12-31 23:45:49 | 31506349293329 | 2.0
2019-12-31 23:46:35 | 31506394434087 | 1.0
因为订单ID 31468414075366在13:13的1小时内只有1个订单,31505523761333在23:32到00:32的1小时内共有3个订单,依此类推
这是一个解决方案。它基于在 'real' 行之后一小时添加人工行的想法。我们将 运行 滚动计数,得到结果,然后将它们匹配回原始时间。这是代码,为清楚起见分为几个步骤。
import datetime
# Create a dataframe with 1 hour time windows
hour_ends = pd.DataFrame({"hour_start": df.index},
index = df.index + datetime.timedelta(hours=1))
# merge the original dataframe and the new one.
t = pd.merge(df, hour_ends, left_index=True, right_index=True, how = "outer")
# do the rolling count.
t["rolling_count"] = t.rolling("1h", closed="both").count()["orderid"]
# match the results back to the starting time.
res = t.reset_index()[["hour_start", "rolling_count"]].dropna()
print (res)
结果是:
hour_start rolling_count
1 2019-12-27 03:06:50 1.0
4 2019-12-27 04:12:50 2.0
5 2019-12-27 05:06:58 1.0
7 2019-12-29 03:00:10 1.0