Python Pandas - объединение на основе подстроки в строке
У меня есть 2 кадра данных в следующем формате:
df_search
SEARCH
part1
anotherpart
onemorepart
df_all
FILE EXTENSION PATH
part1_1 .prt //server/folder1/part1_1
part1_2 .prt //server/folder2/part1_2
part1_2 .pdf //server/folder3/part1_2
part1_3 .prt //server/folder2/part1_3
anotherpart_1 .prt //server/folder1/anotherpart_1
anotherpart_2 .prt //server/folder3/anotherpart_2
anotherpart_3 .prt //server/folder2/anotherpart_3
anotherpart_3 .cgm //server/folder1/anotherpart_3
anotherpart_4 .prt //server/folder3/anotherpart_4
onemorepart_1 .prt //server/folder2/onemorepart_1
onemorepart_2 .prt //server/folder1/onemorepart_2
onemorepart_2 .dwg //server/folder2/onemorepart_2
onemorepart_3 .prt //server/folder1/onemorepart_3
onemorepart_4 .prt //server/folder1/onemorepart_4
Полный df_search имеет 15 000 элементов. У df_all есть 550 000 предметов. Я пытаюсь объединить два кадра данных на основе строки элемента поиска, находящейся в строке файла. Мой желаемый вывод это:
SEARCH FILE EXTENSION PATH
part1 part1_1 .prt //server/folder1/part1_1
part1 part1_2 .prt //server/folder2/part1_2
part1 part1_2 .pdf //server/folder3/part1_2
part1 part1_3 .prt //server/folder2/part1_3
anotherpart anotherpart_1 .prt //server/folder1/anotherpart_1
anotherpart anotherpart_2 .prt //server/folder3/anotherpart_2
anotherpart anotherpart_3 .prt //server/folder2/anotherpart_3
anotherpart anotherpart_3 .cgm //server/folder1/anotherpart_3
anotherpart anotherpart_4 .prt //server/folder3/anotherpart_4
onemorepart onemorepart_1 .prt //server/folder2/onemorepart_1
onemorepart onemorepart_2 .prt //server/folder1/onemorepart_2
onemorepart onemorepart_2 .dwg //server/folder2/onemorepart_2
onemorepart onemorepart_3 .prt //server/folder1/onemorepart_3
onemorepart onemorepart_4 .prt //server/folder1/onemorepart_4
Простое объединение данных не работает, потому что строки никогда не совпадают точно (это всегда подстрока). Я также попробовал следующий метод, основанный на других вопросах здесь на stackru:
df_all[df_all.name.str.contains('|'.join(df_search.search))]
Это дало мне полный список всех найденных элементов в df_all, но я не знаю, какая строка поиска вернула какой результат.
Мне удалось заставить его работать с циклом for, но это медленно (67 минут) с моим набором данных:
super_df = []
for search_item in df_search.search:
df_entire.loc[df_entire.file.str.contains(search_item), 'search'] = search_item
temp_df = df_entire[df_entire.file.str.contains(search_item)]
super_df = pd.concat(super_df, axis=0, ignore_index=True)
Можно ли сделать это с помощью векторизации для повышения производительности?
Спасибо
2 ответа
Использование str.extract
+ insert
:
pat = "|".join(df_search.SEARCH)
df_all.insert(0, 'SEARCH', df_all['FILE'].str.extract("(" + pat + ')', expand=False))
print (df_all)
SEARCH FILE EXTENSION PATH
0 part1 part1_1 .prt //server/folder1/part1_1
1 part1 part1_2 .prt //server/folder2/part1_2
2 part1 part1_2 .pdf //server/folder3/part1_2
3 part1 part1_3 .prt //server/folder2/part1_3
4 anotherpart anotherpart_1 .prt //server/folder1/anotherpart_1
5 anotherpart anotherpart_2 .prt //server/folder3/anotherpart_2
6 anotherpart anotherpart_3 .prt //server/folder2/anotherpart_3
7 anotherpart anotherpart_3 .cgm //server/folder1/anotherpart_3
8 anotherpart anotherpart_4 .prt //server/folder3/anotherpart_4
9 onemorepart onemorepart_1 .prt //server/folder2/onemorepart_1
10 onemorepart onemorepart_2 .prt //server/folder1/onemorepart_2
11 onemorepart onemorepart_2 .dwg //server/folder2/onemorepart_2
12 onemorepart onemorepart_3 .prt //server/folder1/onemorepart_3
13 onemorepart onemorepart_4 .prt //server/folder1/onemorepart_4
Я сделаю это так:
df_all['SEARCH'] = ''
for val in df_search.SEARCH:
df_all.loc[df_all['FILE'].str.match(val), 'SEARCH'] = val