如何在前N行中获取掩码的第一个实例?

0 投票
3 回答
58 浏览
提问于 2025-04-14 15:43

这是我的数据表。

import pandas as pd
df = pd.DataFrame(
    {
        'a': [100, 1123, 9999, 100, 1, 954, 1],
        'b': [1000, 11123, 1123, 0, 55, 0, 1],
    },
)

我希望的结果是创建一列 c

      a      b       c
0   100   1000     NaN
1  1123  11123     NaN
2  9999   1123  9999.0
3   100      0     NaN
4     1     55     NaN
5   954      0     NaN
6     1      1     NaN

这个条件筛选是:

mask = ((df.a > df.b))

我想要找到符合这个条件筛选的第一行数据,但前提是它必须在前3行之内,然后用 df.a 来创建 c。对于这个例子,这段代码可以正常工作:

df.loc[mask.cumsum().eq(1) & mask, 'c'] = df.a

但是对于这个数据表,它应该返回 NaNc,因为符合条件的第一行不在前3行里。但实际上它并没有这样工作。

df = pd.DataFrame(
    {
        'a': [0, 0, 0, 0, 0, 954, 1],
        'b': [1000, 11123, 1123, 0, 55, 0, 1],
    },
)

3 个回答

1

不需要再计算其他的掩码,只需对 df['a'] 进行切片,赋值时会自动重新索引:

mask = df['a'] > df['b']

df.loc[mask, 'c'] = df['a'].iloc[:3]

输出结果:

# example 1
      a      b       c
0   100   1000     NaN
1  1123  11123     NaN
2  9999   1123  9999.0
3   100      0     NaN
4     1     55     NaN
5   954      0     NaN
6     1      1     NaN

# example 2
     a      b   c
0    0   1000 NaN
1    0  11123 NaN
2    0   1123 NaN
3    0      0 NaN
4    0     55 NaN
5  954      0 NaN
6    1      1 NaN
2

如果你希望列 c 的结果和你提问时的一样,可以使用以下代码:

mask = ((df.a > df.b) & (df.index < 3))
df["c"] = df.a[mask]

在最后一行,当 df.a[mask] 被应用时,它会在所有 mask 评估为 False 的行中填入 NaN(缺失值)。所以,这样的结果是:

      a      b       c
0   100   1000     NaN
1  1123  11123     NaN
2  9999   1123  9999.0
3   100      0     NaN
4     1     55     NaN
5   954      0     NaN
6     1      1     NaN
2

你可以根据索引给这个遮罩加个条件:

mask = (df.a > df.b) & (df.index < 3)

对于你的第二个例子,这样做会得到:

     a      b   c
0    0   1000 NaN
1    0  11123 NaN
2    0   1123 NaN
3    0      0 NaN
4    0     55 NaN
5  954      0 NaN
6    1      1 NaN

撰写回答