首页 > 解决方案 > 基于 3 个条件的 Python pandas 数据帧回填

问题描述

我之前的问题的扩展: Python pandas dataframe backfill based on 2 conditions

我有一个这样的数据框:

   Bool   Hour  Min
0  False  12    00
1  False  12    30
2  False  24    00
3  False  24    30
4  False  12    00
5  False  12    30
6  False  24    00
7  False  24    30
8  True   12    00
9  False  12    30
10 False  24    00
11 False  24    30
12 False  12    00
13 False  12    30
14 False  24    00
15 False  24    30
16 False  12    00
17 False  12    30
18 False  24    00
19 False  24    30
20 False  12    00
21 False  12    30
22 False  24    00
23 True   24    30

我想将“Bool”列中的 True 值回填到“Hour”第一次达到“12”和“Min”第一次达到“00”的点。结果将是这样的:

   Bool   Hour  Min  Result
0  False  12    00   False
1  False  12    30   False
2  False  24    00   False
3  False  24    30   False
4  False  12    00   True    <- Desired backfill
5  False  12    30   True    <- Desired backfill
6  False  24    00   True    <- Desired backfill
7  True   24    30   True    <- Desired backfill
8  False  12    00   False
9  False  12    30   False
10 False  24    00   False
11 False  24    30   False
12 False  12    00   False
13 False  12    30   False
14 False  24    00   False
15 False  24    30   False
16 False  12    00   False
17 False  12    30   False
18 False  24    00   False
19 False  24    30   False
20 False  12    00   True    <- Desired backfill
21 False  12    30   True    <- Desired backfill
22 False  24    00   True    <- Desired backfill
23 True   24    30   True    <- Desired backfill

非常感谢任何帮助。非常感谢!

标签: pythonpandasdataframeboolean

解决方案


利用:

m = df['Hour'].eq(12) & df['Min'].eq(0) 
df['Result'] = df['Bool'].shift(-1).groupby(m.cumsum()).transform('any') | df['Bool']

说明

  1. m根据所有Series.eq条件创建布尔掩码==
  2. 然后Series.shift向上一排使用-1
  3. 通过以下方式创建群组Series.cumsum
  4. 使用GroupBy.transformwithGroupBy.any进行True每组测试g
  5. 最后一个链布尔列,|用于按位或

m = df['Hour'].eq(12) & df['Min'].eq(0) 

print (df.assign(m = df['Hour'].eq(12) & df['Min'].eq(0),
                 shift = df['Bool'].shift(-1),
                 g = m.cumsum(),
                 transform = df['Bool'].shift(-1).groupby(m.cumsum()).transform('any'),
                 Result=df['Bool'].shift(-1).groupby(m.cumsum()).transform('any')|df['Bool']))

     Bool  Hour  Min      m  shift  g  transform  Result
0   False    12    0   True  False  1      False   False
1   False    12   30  False  False  1      False   False
2   False    24    0  False  False  1      False   False
3   False    24   30  False  False  1      False   False
4   False    12    0   True  False  2       True    True
5   False    12   30  False  False  2       True    True
6   False    24    0  False  False  2       True    True
7   False    24   30  False   True  2       True    True
8    True    12    0   True  False  3      False    True
9   False    12   30  False  False  3      False   False
10  False    24    0  False  False  3      False   False
11  False    24   30  False  False  3      False   False
12  False    12    0   True  False  4      False   False
13  False    12   30  False  False  4      False   False
14  False    24    0  False  False  4      False   False
15  False    24   30  False  False  4      False   False
16  False    12    0   True  False  5      False   False
17  False    12   30  False  False  5      False   False
18  False    24    0  False  False  5      False   False
19  False    24   30  False  False  5      False   False
20  False    12    0   True  False  6       True    True
21  False    12   30  False  False  6       True    True
22  False    24    0  False   True  6       True    True
23   True    24   30  False    NaN  6       True    True

为@Wen 答案添加新条件:

m = (~df.Bool&df.Hour.eq(12)&df.Min.eq(0))
s=m.iloc[::-1].groupby(df.Bool.iloc[::-1].cumsum()).transform('idxmax')
df['result']=df.index>=s.iloc[::-1]

也对广黄回答如下:

s = df['Bool'].shift(-1)
m = df['Hour'].eq(12) & df['Min'].eq(0)
df['Result'] = df['Bool'] | s.where(s).groupby(m.cumsum()).bfill()

推荐阅读