Python - поиск строки в кадре данных из списка - PullRequest
4 голосов
/ 06 марта 2019

У меня есть следующий список:

search_list = ['STEEL','IRON','GOLD','SILVER']

, который мне нужно найти в кадре данных (df):

      a    b             
0    123   'Blah Blah Steel'
1    456   'Blah Blah Blah'
2    789   'Blah Blah Gold'

и вставить соответствующие строки в новый кадр данных (newdf), добавив новый столбец с соответствующим словом из списка:

      a    b                   c
0    123   'Blah Blah Steel'   'STEEL'
1    789   'Blah Blah Gold'    'GOLD'

Я могу использовать следующий код для извлечения соответствующей строки:

newdf=df[df['b'].str.upper().str.contains('|'.join(search_list),na=False)]

, но я не могу понятьКак добавить подходящее слово из списка в столбец c.

Я думаю, что совпадение каким-то образом должно захватывать индекс соответствующего слова в списке и затем извлекать значение, используя индексный номер, ноЯ не могу понять, как это сделать.

Любая помощь или указатели будут с благодарностью

Спасибо

Ответы [ 7 ]

5 голосов
/ 06 марта 2019

Вы можете использовать извлекать и отфильтровывать те, которые nan (то есть не совпадают):

search_list = ['STEEL','IRON','GOLD','SILVER']

df['c'] = df.b.str.extract('({0})'.format('|'.join(search_list)), flags=re.IGNORECASE)
result = df[~pd.isna(df.c)]

print(result)

выход

              a       b      c
123 'Blah  Blah  Steel'  Steel
789 'Blah  Blah   Gold'   Gold

Обратите внимание, что вы должны импортировать модуль re, чтобы использовать флаг re.IGNORECASE. В качестве альтернативы вы можете использовать 2 напрямую, что является значением флага re.IGNORECASE.

ОБНОВЛЕНИЕ

Как уже упоминалось @ user3483203, вы можете сохранить импорт, используя:

df['c'] = df.b.str.extract('(?i)({0})'.format('|'.join(search_list)))
3 голосов
/ 06 марта 2019

Вы можете использовать set.intersection, чтобы найти, какие слова появляются в столбце b:

search_list = set(['STEEL','IRON','GOLD','SILVER'])
df['c'] = df['b'].apply(lambda x: set.intersection(set(x.upper().split(' ')), search_list))

Вывод:

     a                b        c
0  123  Blah Blah Steel  {STEEL}
1  456   Blah Blah Blah       {}
2  789   Blah Blah Gold   {GOLD}

Используйте df[df['c'].astype(bool)], если хотите избавитьсястрок без совпадения

     a                b        c
0  123  Blah Blah Steel  {STEEL}
2  789   Blah Blah Gold   {GOLD}
1 голос
/ 06 марта 2019

Вы также можете сделать:

import pandas as pd

search_list = ('STEEL','IRON','GOLD','SILVER')

df = pd.DataFrame({'a':[123,456,789],'b':['blah blah Steel','blah blah blah','blah blah Gold']})

df.assign(c = df['b'].apply(lambda x: [j for j in x.split() if j.upper() in search_list]))

Результаты: enter image description here

1 голос
/ 06 марта 2019

Здесь, решение с конечным результатом, как ваш дисплей:

search_list = ['STEEL','IRON','GOLD','SILVER']

def process(x):
    for s in search_list:
        if s in x['b'].upper(): print("'"+ s +"'");return "'"+ s +"'"
    return ''

df['c']= df.apply(lambda x: process(x),axis=1)
df = df.drop(df[df['c'] == ''].index).reset_index(drop=True)

print(df)

выход:

     a                 b        c
0  123  'Blah Blah Steel  'STEEL'
1  789  'Blah Blah Gold'   'GOLD'
1 голос
/ 06 марта 2019

Использование

s=pd.DataFrame(df.b.str.upper().str.strip("'").str.split(' ').tolist())
s.where(s.isin(search_list),'').sum(1)
Out[492]: 
0    STEEL
1         
2     GOLD
dtype: object
df['New']=s.where(s.isin(search_list),'').sum(1)
df
Out[494]: 
     a                  b    New
0  123  'Blah Blah Steel'  STEEL
1  456   'Blah Blah Blah'       
2  789   'Blah Blah Gold'   GOLD
1 голос
/ 06 марта 2019

Один из способов сделать это -

def get_word(my_string):
    for word in search_list:
         if word.lower() in my_string.lower():
               return word
    return None

new_df["c"]= new_df["b"].apply(get_word)

Вы также можете сделать что-то вроде

new_df["c"]= new_df["b"].apply(lambda my_string: [word for word in search_list if word.lower() in my_string.lower()][0])

С первым вы можете добавить столбец c до df сначала, а затем отфильтровывает None с, а второй выдает ошибку, если b не содержит ни одного слова.

Вы также можете увидеть этот вопрос: Получить первый элемент из повторяемого элемента, который соответствует условию

Применение метода из рейтинга с наивысшим рейтингом даст

new_df["c"]= new_df["b"].apply(lambda my_string: next(word for word in search_list if word.lower() in my_string.lower())
1 голос
/ 06 марта 2019

Вы можете использовать:

search_list = ['STEEL','IRON','GOLD','SILVER']
pat = r'\b|\b'.join(search_list)
pat2 = r'({})'.format('|'.join(search_list))

df_new= df.loc[df.b.str.contains(pat,case=False,na=False)].reset_index(drop=True)
df_new['new_col']=df_new.b.str.upper().str.extract(pat2)
print(df_new)

     a                  b new_col
0  123  'Blah Blah Steel'   STEEL
1  789   'Blah Blah Gold'    GOLD
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...