Pandas: заменить значения строкового столбца (равно, содержит, регистр) - PullRequest
1 голос
/ 03 апреля 2020

У меня есть datafarme, как показано ниже.

ID   COUNTRY   GENDER    AGE  V1   V2   V3   V4   V5
1    1    1    53   APPLE     apple     bosck     APPLE123  xApple111t
2    2    2    51   BEKO beko SIMSUNG   SamsungO123    ttBeko111t
3    3    1    24   SAMSUNG   bosch     SEMSUNG   BOSC1123  uuSAMSUNG111t

Я хочу заменить на np.nan, если в списке есть такое же значение или указано конкретное значение c. Я пробовал ниже, но произошла ошибка.

remove_list = ['APPLE', 'BEKO']

remove_contain_list = ['SUNG', 'bosc']

df.iloc[:,4:].str.replace(remove_list, np.nan, case=False) # exact match & case sensitive
df.iloc[:,4:].str.contains(remove_contain_list, np.nan, case=False) # contain & case sensitive

Как я могу решить эти проблемы?

1 Ответ

1 голос
/ 03 апреля 2020

Вы можете создать MultiIndex Series с помощью DataFrame.stack, получить маски для точных и частичных совпадений с помощью Series.isin со значениями в нижнем регистре и Series.str.contains замените на Series.mask (значение по умолчанию для замены NaN, поэтому указывать необязательно) и введите Series.unstack и присвойте обратно:

remove_list = ['APPLE', 'BEKO']
remove_contain_list = ['SUNG', 'bosc']

s = df.iloc[:,4:].stack(dropna=False)
m1 = s.str.lower().isin([x.lower() for x in remove_list])
m2 = s.str.contains('|'.join(remove_contain_list), case=False)
s = s.mask(m1 | m2)

df.iloc[:,4:] = s.unstack()
print (df)
   ID  COUNTRY  GENDER  AGE   V1   V2   V3        V4          V5
0   1        1       1   53  NaN  NaN  NaN  APPLE123  xApple111t
1   2        2       2   51  NaN  NaN  NaN       NaN  ttBeko111t
2   3        3       1   24  NaN  NaN  NaN       NaN         NaN

РЕДАКТИРОВАТЬ: Вы можете заменить маску на цвет фона, если совпадают в Styler.apply:

def color(x): 
    c1 = 'background-color: yellow'
    c = ''

    remove_list = ['APPLE', 'BEKO']
    remove_contain_list = ['SUNG', 'bosc']

    s = x.iloc[:,4:].stack(dropna=False)
    m1 = s.str.lower().isin([i.lower() for i in remove_list])
    m2 = s.str.contains('|'.join(remove_contain_list), case=False)
    m = m1| m2

    df1 = pd.DataFrame(c, index=x.index, columns=x.columns)
    mask = m.unstack(fill_value=False).reindex(x.columns, fill_value=False, axis=1)   
    df1 = df1.mask(mask, c1)
    return df1

df.style.apply(color,axis=None)
...