如何用Pandas groupby按条件返回布尔值?附连续用餐场景求解
解决连续3天吃披萨的用户判断问题
需求回顾
我们有一份记录用户每日晚餐的DataFrame,日期格式为dd/mm/yyyy,今日是05/02/2019,需要生成一个新的DataFrame,标记每个用户是否从昨天起连续3天(即02/02/2019-04/02/2019)都吃了披萨。
原始数据:
person_id, date, dinner 1, 01/02/2019, pizza 1, 02/02/2019, pizza 1, 03/02/2019, pizza 1, 04/02/2019, pizza 2, 01/02/2019, burger 2, 02/02/2019, sushi 2, 03/02/2019, burger 2, 04/02/2019, pizza 3, 01/02/2019, burger 3, 02/02/2019, pizza 3, 03/02/2019, pizza 3, 04/02/2019, pizza
期望结果:
person_id, eat_pizza_3_days_in_row 1, True 2, False 3, True
解决方案步骤
你已经走到了筛选和分组的关键步骤,接下来只需要对分组后的数据做两个核心检查:这三天的晚餐全是披萨,并且用户在这三天里每天都有记录(避免某一天没数据但剩下两天是披萨的误判)。
具体代码如下:
import pandas as pd # 构造原始DataFrame data = [ [1, "01/02/2019", "pizza"], [1, "02/02/2019", "pizza"], [1, "03/02/2019", "pizza"], [1, "04/02/2019", "pizza"], [2, "01/02/2019", "burger"], [2, "02/02/2019", "sushi"], [2, "03/02/2019", "burger"], [2, "04/02/2019", "pizza"], [3, "01/02/2019", "burger"], [3, "02/02/2019", "pizza"], [3, "03/02/2019", "pizza"], [3, "04/02/2019", "pizza"], ] df = pd.DataFrame(data, columns=["person_id", "date", "dinner"]) # 第一步:把字符串日期转换成datetime类型,避免字符串比较的bug df["date"] = pd.to_datetime(df["date"], format="%d/%m/%Y") # 计算目标时间窗口:昨天及前两天(2019-02-02 至 2019-02-04) yesterday = pd.to_datetime("05/02/2019") - pd.Timedelta(days=1) three_days_ago = yesterday - pd.Timedelta(days=2) # 筛选出目标时间范围内的记录 filtered_df = df[(df["date"] >= three_days_ago) & (df["date"] <= yesterday)] # 第二步:分组后执行判断逻辑 result = filtered_df.groupby("person_id").apply( lambda x: (x["dinner"] == "pizza").all() and len(x) == 3 ).reset_index(name="eat_pizza_3_days_in_row") print(result)
代码关键细节解释
- 日期转换:必须先把字符串日期转成
datetime类型,否则跨月份的日期字符串比较会出现错误(比如"01/03/2019"和"04/02/2019"的字符串比较结果会不符合时间逻辑)。 - 时间窗口计算:用
Timedelta自动计算日期,比手动写死日期字符串更灵活,也能避免输入错误。 - 分组判断逻辑:
(x["dinner"] == "pizza").all():确保用户在目标窗口内的每一顿晚餐都是披萨。len(x) == 3:保证用户这三天每天都有晚餐记录,排除“某一天没记录但剩下两天吃披萨”的误判情况。
运行这段代码后,输出结果会完全匹配你的期望!
内容的提问来源于stack exchange,提问作者andrewshih
相关产品推荐
相关产品推荐

