Заполните поля, где равно значение, до другого значения - Pandas - PullRequest
2 голосов
/ 05 марта 2020

Я пытаюсь ffill() значения в двух столбцах в df на основе отдельного столбца. Я надеюсь продолжить заполнение, пока не будет выполнено условие. Используя df ниже, где Val1 и Val2 равны C, я хочу заполнить последующие строки, пока строки в Code не начнутся с ['FR','GE','GA'].

import pandas as pd
import numpy as np

df = pd.DataFrame({   
    'Code' : ['CA','GA','YA','GE','XA','CA','YA','FR','XA'],             
    'Val1' : ['A','B','C','A','B','C','A','B','C'],                 
    'Val2' : ['A','B','C','A','B','C','A','B','C'],
   })

mask = (df['Val1'] == 'C') & (df['Val2'] == 'C')

cols = ['Val1', 'Val2']

df[cols] = np.where(mask, df[cols].ffill(), df[cols])

Предполагаемый вывод:

  Code Val1 Val2
0   CA    A    A
1   GA    B    B
2   YA    C    C
3   GE    A    A
4   XA    B    B
5   CA    C    C
6   YA    C    C
7   FR    B    B
8   XA    C    C

Примечание. Строки в Code сокращены до двух символов, но длиннее в моем наборе данных, поэтому я надеюсь использовать startswith

1 Ответ

2 голосов
/ 05 марта 2020

Проблема похожа на сигнал пуска / остановки, на который я отвечал ранее, но не смог его найти. Итак, вот решение наряду с другими упомянутыми вами вещами:

# check for C
is_C = df.Val1.eq('C') & df.Val2.eq('C')

# check for start substring with regex
startswith = df.Code.str.match("^(FR|GE|GA)")

# merge the two series
# startswith is 0, is_C is 1
mask = np.select((startswith,is_C), (0,1), np.nan)

# update mask with ffill 
# rows after an `is_C` and before a `startswith` will be marked with 1
mask = pd.Series(mask, df.index).ffill().fillna(0).astype(bool);

# update the dataframe
df.loc[mask, ['Val1','Val2']] = 'C'

Вывод

  Code Val1 Val2
0   CA    A    A
1   GA    B    B
2   YA    C    C
3   GE    A    A
4   XA    B    B
5   CA    C    C
6   YA    C    C
7   FR    B    B
8   XA    C    C
...