Определение, содержит ли столбец данных Pandas элемент из списка - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть фрейм данных, содержащий большое количество строк (несколько миллионов).Один из столбцов содержит строку, содержащую список, разделенный запятыми (но не список Python, а просто список элементов, разделенных запятыми).Кадр данных может быть представлен как:

df = pd.DataFrame({'A':['a,b,c','b,c,d,e','a,b,e,f','a,c,d,f']})

         A
0    a,b,c
1  b,c,d,e
2  a,b,e,f
3  a,c,d,f

У меня есть отдельный список Python, содержащий различные элементы, такие как:

lst1 = ['w','x','y','z','b']

Я хотел бы создать дополнительный столбец в базе данных, который указывает, содержится ли один из элементов в lst1 в столбце базы данных A.

Мое решение состояло в том, чтобы преобразовать элементы списка врегулярное выражение и использование структуры .str.contains() для обозначения строк как True или False:

regex = regex = '|'.join(['(?:{})'.format(i) for i in lst1])

Это приводит к следующему регулярному выражению:

(?:w)|(?:x)|(?:y)|(?:z)|(?:b)

Тогда:

df['B'] = df['A'].str.contains(regex)

         A      B
0    a,b,c   True
1  b,c,d,e   True
2  a,b,e,f   True
3  a,c,d,f  False

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

РЕДАКТИРОВАТЬ

После ответа @jezrael я провел сравнение по времени.Я сгенерировал фрейм данных со строками 4M и списком элементов, которые нужно идентифицировать следующим образом:

import timeit

df = pd.DataFrame({'A':['the,cat,sat,on,mat','the,cow,jumped,over,moon','humpty,dumpty,sat,on,the,wall','tiger,burning,bright']*1000000})

terms = ['sat','mat','moon','small','large','home','sliced']
regex = '|'.join(['(?:{})'.format(i) for i in terms])

%timeit df['B'] = df['A'].str.contains(regex)

Это привело к:

1 loop, best of 3: 8.09 s per loop

По сравнению с:

import timeit

df = pd.DataFrame({'A':['the,cat,sat,on,mat','the,cow,jumped,over,moon','humpty,dumpty,sat,on,the,wall','tiger,burning,bright']*1000000})

terms = ['sat','mat','moon','small','large','home','sliced']
s = set(terms)

%timeit df['B1'] = [bool(set(x.split(',')) & s) for x in df['A']]

Это дало:

1 loop, best of 3: 8.36 s per loop

Столь схожие результаты в этой конкретной установке, хотя, как говорит @jezrael, на производительность параметра regex будут влиять множество факторов, таких как длина строк, количество совпадений,и т.д.

1 Ответ

0 голосов
/ 19 февраля 2019

Одним из решений, не относящихся к регулярным выражениям, является использование пересечения множеств и преобразование в bool:

s = set(lst1)
df['B1'] = [bool(set(x.split(',')) & s) for x in df['A']]
print (df)
         A      B     B1
0    a,b,c   True   True
1  b,c,d,e   True   True
2  a,b,e,f   True   True
3  a,c,d,f  False  False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...