You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

分组后动态移除首尾满足条件的行(基于非零值判断)

按组移除首尾连续全零行,保留中间零行

需求说明

按year列对DataFrame分组,完成以下操作:

  • 移除每组开头连续的val1/val2/val3全为0的行,直到遇到第一个非全零行
  • 移除每组末尾连续的全零行
  • 组内中间的零行必须保留

原始数据

创建DataFrame的代码:

import pandas as pd

data = {'year': [2019,2019,2019,2019,2019,2019,2019,2019,2020,2020,2020,2020,2020,2020],
        'month': [1,2,3,4,5,6,7,8,5,6,7,8,9,10],
        'val1': [0,0,0,0,1,0,0,0,0,0,1,0,0,0],
        'val2': [0,0,1,0,1,0,0,0,1,0,1,0,0,0],
        'val3': [0,0,0,0,1,1,0,0,0,0,1,1,0,0]}
df = pd.DataFrame(data)

原始数据打印输出:

+------+-------+------+------+------+
| year | month | val1 | val2 | val3 |
+------+-------+------+------+------+
| 2019 | 1     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2019 | 2     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2019 | 3     | 0    | 1    | 0    |
+------+-------+------+------+------+
| 2019 | 4     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2019 | 5     | 1    | 1    | 1    |
+------+-------+------+------+------+
| 2019 | 6     | 0    | 0    | 1    |
+------+-------+------+------+------+
| 2019 | 7     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2019 | 8     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2020 | 5     | 0    | 1    | 0    |
+------+-------+------+------+------+
| 2020 | 6     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2020 | 7     | 1    | 1    | 1    |
+------+-------+------+------+------+
| 2020 | 8     | 0    | 0    | 1    |
+------+-------+------+------+------+
| 2020 | 9     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2020 | 10    | 0    | 0    | 0    |
+------+-------+------+------+------+

期望输出

+------+-------+------+------+------+
| year | month | val1 | val2 | val3 |
+------+-------+------+------+------+
| 2019 | 3     | 0    | 1    | 0    |
+------+-------+------+------+------+
| 2019 | 4     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2019 | 5     | 1    | 1    | 1    |
+------+-------+------+------+------+
| 2019 | 6     | 0    | 0    | 1    |
+------+-------+------+------+------+
| 2020 | 5     | 0    | 1    | 0    |
+------+-------+------+------+------+
| 2020 | 6     | 0    | 0    | 0    |
+------+-------+------+------+------+
| 2020 | 7     | 1    | 1    | 1    |
+------+-------+------+------+------+
| 2020 | 8     | 0    | 0    | 1    |
+------+-------+------+------+------+

实现代码

import pandas as pd

# 原始数据创建
data = {'year': [2019,2019,2019,2019,2019,2019,2019,2019,2020,2020,2020,2020,2020,2020],
        'month': [1,2,3,4,5,6,7,8,5,6,7,8,9,10],
        'val1': [0,0,0,0,1,0,0,0,0,0,1,0,0,0],
        'val2': [0,0,1,0,1,0,0,0,1,0,1,0,0,0],
        'val3': [0,0,0,0,1,1,0,0,0,0,1,1,0,0]}
df = pd.DataFrame(data)

# 标记每行是否为val1/val2/val3全零行
df['is_all_zero'] = (df[['val1', 'val2', 'val3']] == 0).all(axis=1)

# 定义分组处理函数:裁剪首尾连续全零行
def trim_group(group):
    # 找到组内第一个非全零行的索引
    first_valid = (~group['is_all_zero']).idxmax()
    # 找到组内最后一个非全零行的索引
    last_valid = (~group['is_all_zero'])[::-1].idxmax()
    # 截取有效区间内的行,去掉标记列
    return group.loc[first_valid:last_valid].drop('is_all_zero', axis=1)

# 分组应用处理函数,合并结果
result_df = df.groupby('year', group_keys=False).apply(trim_group)

# 打印验证结果
print(result_df)

逻辑说明

  • 标记全零行:用(df[cols] ==0).all(axis=1)快速判断每行是否满足val1、val2、val3全为0的条件
  • 找第一个有效行:(~group['is_all_zero']).idxmax()利用布尔值的数值特性(True=1,False=0),直接取第一个True的索引,也就是第一个非全零行的位置
  • 找最后一个有效行:把布尔序列反转后再取idxmax,就能得到最后一个非全零行的索引
  • 切片保留有效区间:通过loc[first:last]直接截取中间部分,自然保留了组内中间的零行

内容的提问来源于stack exchange,提问作者adama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 02:54:22