Векторизованная реализация повышает KeyError при использовании loc напрямую для присвоения значения на основе условия

#python-3.x #pandas #dataframe

#python-3.x #панды #фрейм данных

Вопрос:

После чтения CSV-файла

 Date,Description,Price
15/11/2020,Red blah,51
13/11/2020,blah Blue,24
10/11/2020,Green blah,10
09/11/2020,blah Green,21
08/11/2020,blah Blue blah,42
 

Я хочу добавить новый столбец ( category ) и присвоить ему строковое значение, если какая-либо из подстрок в list ( keys ) содержится внутри строки другого столбца ( description ).

Мне удалось добиться этого с помощью for цикла, но когда я пытаюсь реализовать его с помощью векторизованного решения, оно вызывает KeyError:

KeyError: «Ни один из [Index([‘Red’, ‘Blue’, ‘Green’, ‘Green’, ‘Blue’], dtype=’object’)] не находится в [index]»

даже подумал, что ключ явно существует.

Мой код:

 import pandas

df = pandas.read_csv('my.csv',
                     header=0,
                     names=['date',
                            'description',
                            'price'],
                     dayfirst=True,
                     parse_dates=True)

keys = ['Green', 'Blue']
df['category'] = ''

# with for loop
for index in df.index:
    if any(key in df.loc[index, 'description'] for key in keys):
        df.loc[index, 'category'] = 'CYAN'
    else:
        df.loc[index, 'category'] = 'NOT CYAN'

# with vectorized solution raises KeyError
# df.loc[any(key in df.loc[df['description']] for key in keys), 'category'] = 'CYAN'
# df.loc[any(key not in df.loc[df['description']] for key in keys), 'category'] = 'NOT CYAN'

print(df)
 

Приведенный выше код с for циклом возвращает ожидаемое:

          date description  price  category
0  08/11/2020        Blue     42      CYAN
1  09/11/2020       Green     21      CYAN
2  10/11/2020       Green     10      CYAN
3  13/11/2020        Blue     24      CYAN
4  15/11/2020         Red     51  NOT CYAN
 

Любые предложения о том, как реализовать вышеизложенное, используя векторизованный подход?

Ответ №1:

Использование np.where :

 df['category'] = np.where(df['Description'].isin(keys), 'CYAN', 'NOT CYAN')
 

Вывод:

         Date Description  Price  category
0 2020-11-15         Red     51  NOT CYAN
1 2020-11-13        Blue     24      CYAN
2 2020-11-10       Green     10      CYAN
3 2020-11-09       Green     21      CYAN
4 2020-11-08        Blue     42      CYAN
 

Обновление: Для подстроки используйте str.contains :

 pattern = '|'.join(keys)

df['category'] = np.where(df['Description'].str.contains(rf'{pattern}'), 
                          'CYAN', 'NOT CYAN')
 

Вывод:

         Date     Description  Price  category
0 2020-11-15        Red blah     51  NOT CYAN
1 2020-11-13       blah Blue     24      CYAN
2 2020-11-10      Green blah     10      CYAN
3 2020-11-09      blah Green     21      CYAN
4 2020-11-08  blah Blue blah     42      CYAN
 

Комментарии:

1. numpy’s where кажется замечательным, спасибо. Но, пожалуйста, обратите внимание, что это keys подмножество; Я изменил вопрос, чтобы сделать его явным в примере. Есть ли способ использовать np.where , чтобы он соответствовал, когда список ключей является подмножеством столбца описания?