Мне нужно отфильтровать из фрейма данных, если элемент поиска найден в столбце (например, идентификация всех сотрудников-empID с искомой областью знаний
import pandas as pd
date=[
[123,['abc','def','efg']],
[124,['abc','qwe','mno']],
[124,['abc','qwe','mno']],
[126,['wer','abc']]
]
expertise_df=pd.DataFrame(date,columns=['EmpId','areas'])
Я пытаюсь отфильтровать строки с буквами «abc» или «qwe» и т. д., но без явного создания циклов во всех строках и проверки на соответствие. Я пробовал expert_df['areas'.str.contains, но это не дает результатов. Это будет соответствовать около 1000 строк поиска в 200 000 строк в expertness_df и, следовательно, искать эффективные по времени подходы. Подход грубой силы занимает более 4 часов и непрактичен.
Кроме того, если мне нужно создать операции объединения (содержащие либо «abc», либо «pqr» и т. д.), есть ли способ обрабатывать результаты как наборы, чтобы включить это?
Чтобы отфильтровать строки, содержащие qwe
в качестве элемента списка во втором столбце expertise_df
, можно сделать:
expertise_df[
pd.DataFrame(
expertise_df.explode('areas')\
['areas'].str.contains('qwe'))\
.reset_index()\
.groupby('index')\
.any()['areas']]
Это даст вам:
EmpId areas
1 124 [abc, qwe, mno]
2 124 [abc, qwe, mno]
Если вы хотите найти строки, которые содержат любой элемент списка, то есть:
searchfor = ['wer','def']
затем сделайте это, используя Как отфильтровать строки, содержащие строковый шаблон из фрейма данных Pandas:
expertise_df[
pd.DataFrame(
expertise_df.explode('areas')\
['areas'].str.contains('|'.join(searchfor)))\
.reset_index()\
.groupby('index')\
.any()['areas']]
Если вы хотите проверить несколько значений (например, ['def', 'wer']
), вы можете использовать отрицание apply с isdisjoint.
mask = ~expertise_df['areas'].apply(frozenset(['def', 'wer']).isdisjoint)
res = expertise_df[mask]
print(res)
Выход
EmpId areas
0 123 [abc, def, efg]
3 126 [wer, abc]
Вы можете использовать набор пересечений для фильтрации нужных строк.
import pandas as pd
date=[
[123,['abc','def','efg']],
[124,['abc','qwe','mno']],
[124,['abc','qwe','mno']],
[126,['wer','abc']]
]
expertise_df=pd.DataFrame(date,columns = ['EmpId','areas'])
filter_set = {'def','wer'}
filtered_df=expertise_df[expertise_df['areas'].
apply(lambda el: bool(filter_set.intersection(el)))]
print(filtered_df)
Выход:
EmpId areas
0 123 [abc, def, efg]
3 126 [wer, abc]
Хороший ответ, проще моего.