首页 > 解决方案 > 获取连续出现 n 次的值

问题描述

我有一个具有以下结构的 DataFrame:

用户身份 日期 店铺
12 2020 年 1 月 1 日 红色的
12 2020 年 1 月 1 日 橙子
12 2020 年 1 月 1 日 红色的
12 13/01/2020 红色的
12 15/02/2020 蓝色的
12 20/02/2020 蓝色的
12 20/02/2020 蓝色的
13 2020 年 1 月 1 日 橙子
13 25/01/2020 橙子

所以我想要的是选择用户连续购买 3 次(或更多)的最后一个商店。如果连续购买少于 3 次 - 应选择最后一家商店。

例如,上表的结果将如下所示:

用户身份 店铺
12 蓝色的
13 橙子

如何在 Python 中使用 Pandas 执行此操作?

标签: pythonpandas

解决方案


解决方案

m1 = df['Store'] != df['Store'].shift()

m2 = df.groupby(['UserId', m1.cumsum()])['Store'].transform('count').ge(3)
m3 = m2.groupby(df['UserId']).transform('any')

out = df[m2 | ~m3].drop_duplicates('UserId', keep='last')

解释

  • 将其中的值Store与前一个值进行比较以创建布尔掩码m1
>>> m1

# 0      True
# 1      True
# 2      True
# 3     False
# 4      True
# 5     False
# 6     False
# 7      True
# 8     False
# 9      True
# 10     True
# Name: Store, dtype: bool
  • 计算掩码上的累积和以识别存储列中的值保持不变的行块,然后将数据帧UserId与这些块一起分组,并transform用于count计算用户对每个商店的连续访问次数。现在比较连续访问的计数3以创建一个布尔掩码m2
>>> m2

# 0     False
# 1     False
# 2     False
# 3     False
# 4      True
# 5      True
# 6      True
# 7     False
# 8     False
# 9     False
# 10    False
# Name: Store, dtype: bool
  • 对上一步中创建的掩码进行分组,UserIdtransform用于any确定用户是否连续访问过任何一家商店至少 3 次
>>> m3

# 0      True
# 1      True
# 2      True
# 3      True
# 4      True
# 5      True
# 6      True
# 7     False
# 8     False
# 9     False
# 10    False
# Name: Store, dtype: bool
  • 取逻辑或m2而不m3过滤行,然后删除重复值,保留最后一行UserId
>>> out

#    UserId        Date   Store
# 6      12  20/02/2020    Blue
# 8      13  25/01/2020  Orange

推荐阅读