У меня есть фрейм данных, содержащий большое количество строк (несколько миллионов).Один из столбцов содержит строку, содержащую список, разделенный запятыми (но не список 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 будут влиять множество факторов, таких как длина строк, количество совпадений,и т.д.