如何在DataFrame中满足条件后选择连续行?附示例
解决DataFrame分组后按日期排序并保留首次stock>0后所有行的问题
我来帮你搞定这个需求!你想要按style分组,先按日期顺序排序,再保留每个组里首次出现stock>0之后的所有行(包括那一行本身,以及之后的0值行)对吧?之前尝试分组加条件没得到结果,大概率是没处理日期的正确排序,或者没找到筛选首次触发点后所有行的方法,咱们一步步来实现:
步骤1:处理日期的有序性
星期几的字符串默认是按字母排序的(比如fri会排在mon前面),这完全不符合我们的日期逻辑,所以首先要把day列转换成有序类别,让pandas知道正确的星期顺序:
import pandas as pd # 定义星期的自然顺序 week_order = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat'] dfA['day'] = pd.Categorical(dfA['day'], categories=week_order, ordered=True)
步骤2:分组并按日期排序
接下来按style分组,每个组内部按照我们定义的日期顺序排序:
# 分组后每组按day排序,group_keys=False避免生成额外的分组索引 df_sorted = dfA.groupby('style', group_keys=False).apply(lambda x: x.sort_values('day'))
步骤3:筛选首次stock>0后的所有行
这里用一个很实用的小技巧:先标记出所有stock>0的行,然后用cumsum()计算累积和——第一次遇到stock>0时,累积和变成1,之后的所有行累积和都会≥1,这样就能轻松筛选出首次触发点后的所有行:
result = df_sorted.groupby('style').apply( lambda x: x[x['stock'].gt(0).cumsum() >= 1] ).reset_index(drop=True)
完整代码与验证
把所有步骤整合起来,加上你的示例数据,运行后就能得到正确结果:
import pandas as pd # 你的示例数据 data = { 'style': ['pants', 'pants', 'pants', 'pants', 'pants', 'pants', 'shirt', 'shirt', 'shirt', 'shirt', 'shirt', 'shirt'], 'day': ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sat', 'thu', 'mon', 'tue', 'wed', 'fri'], 'stock': [0, 2, 1, 0, 1, 0, 1, 2, 0, 0, 2, 0] } dfA = pd.DataFrame(data) # 1. 设置日期有序性 week_order = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat'] dfA['day'] = pd.Categorical(dfA['day'], categories=week_order, ordered=True) # 2. 分组排序 df_sorted = dfA.groupby('style', group_keys=False).apply(lambda x: x.sort_values('day')) # 3. 筛选目标行 result = df_sorted.groupby('style').apply( lambda x: x[x['stock'].gt(0).cumsum() >= 1] ).reset_index(drop=True) # 打印结果 print(result)
运行后输出:
style day stock 0 pants tue 2 1 pants wed 1 2 pants thu 0 3 pants fri 1 4 pants sat 0 5 shirt wed 2 6 shirt thu 2 7 shirt fri 0 8 shirt sat 1
注意点说明
你给出的期望输出中,shirt的行没有按日期排序,而按照需求里“按日期排序后”的要求,正确的顺序应该是mon→tue→wed→thu→fri→sat,所以最终shirt组是从首次stock>0的wed开始,保留之后的所有有序行,这和我们的输出一致。
内容的提问来源于stack exchange,提问作者Aatish Kayyath
相关产品推荐
相关产品推荐

