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

如何定位Pandas DataFrame中符合条件的最后连续序列首元素并获取该行?

问题与解决方案

问题描述

给定如下DataFrame:

import pandas as pd
df = pd.DataFrame({'a': [1, 0, 0, 1, 0, -1, -1, -1, 0, -1, -1, -1]})

期望得到如下输出:

a    b
0   1  NaN
1   0  NaN
2   0  NaN
3   1  NaN
4   0  NaN
5  -1  NaN
6  -1  NaN
7  -1  NaN
8   0  NaN
9  -1  x
10 -1  NaN
11 -1  NaN

需要找到数据列中的最后一个连续序列(示例中为-1),并标记该序列的第一个元素,同时需满足以下四个条件:

  • 排除由0组成的连续序列;
  • 连续序列长度至少为2行;
  • 若最后一个连续序列是0,则不标记任何内容;
  • 若最后一个非0连续序列长度不足2行,也不进行标记。

用户尝试了以下代码但未成功:

mask = (df.a == -1)
df.loc[(mask.cumsum() == mask.sum() - 1) & mask, 'b'] = 'x'

另外,用户还想知道:找到目标行后,如何在不创建新列(如上述代码中的b列)的情况下获取该行?目前习惯是创建新列后筛选非NaN值的行。

解决方案

1. 实现标记目标行的逻辑

要满足所有条件,我们可以通过分组连续相同值的方式来处理:

import pandas as pd

df = pd.DataFrame({'a': [1, 0, 0, 1, 0, -1, -1, -1, 0, -1, -1, -1]})

# 生成连续相同值的分组标签
df['group'] = (df['a'] != df['a'].shift()).cumsum()

# 计算每个分组的长度、值
group_info = df.groupby('group')['a'].agg(
    value='first',
    length='count'
).reset_index()

# 筛选符合条件的目标分组:非0、长度≥2、是最后一个非0分组
target_group = group_info[
    (group_info['value'] != 0) &
    (group_info['length'] >= 2)
].tail(1)

# 标记该分组的第一行
if not target_group.empty:
    df['b'] = pd.NA
    target_idx = df[df['group'] == target_group['group'].iloc[0]].index[0]
    df.loc[target_idx, 'b'] = 'x'

# 删除临时分组列
df = df.drop('group', axis=1)

print(df)

核心逻辑说明:

  • 用shift()对比前后值,生成连续相同值的分组ID;
  • 统计每个分组的基本信息(值、长度);
  • 筛选出最后一个满足「非0、长度≥2」的分组;
  • 标记该分组的第一行为x,其余行设为NaN。

2. 不创建新列直接获取目标行

如果不需要标记列,直接获取目标行,可以跳过创建b列的步骤,直接提取索引:

import pandas as pd

df = pd.DataFrame({'a': [1, 0, 0, 1, 0, -1, -1, -1, 0, -1, -1, -1]})

# 生成分组标签
df['group'] = (df['a'] != df['a'].shift()).cumsum()

# 分组统计
group_info = df.groupby('group')['a'].agg(
    value='first',
    length='count'
).reset_index()

# 筛选目标分组
target_group = group_info[
    (group_info['value'] != 0) &
    (group_info['length'] >= 2)
].tail(1)

# 获取目标行(如果存在)
if not target_group.empty:
    target_row = df[df['group'] == target_group['group'].iloc[0]].iloc[0]
    print("目标行:")
    print(target_row)
else:
    print("没有符合条件的目标行")

# 清理临时列
df = df.drop('group', axis=1)

这样就能直接得到目标行,无需创建额外的标记列。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:07:38