Я нашел решение своей проблемы, но оно явно самое тупое и неэффективное. Я надеялся, что кто-нибудь сможет помочь мне с правильным решением.
У меня есть два фрейма данных, содержащие столбец с номером телефона. df1["telephone"] может содержать один или несколько номеров, разделенных запятыми, а df2["telephone"] содержит только отдельные цифры:
df1["telephone"]
telephone
115879878
411564656
465464654,45646546
464665465,46456465,87972315
123165648
df2["telephone"]
telephone
156465456
132131321
879878999
456489798
546489798
465478978
Я хочу проверить, находится ли один из номеров в df1["телефон"] в df2["телефон"] и создать столбец с совпадающим номером.
Мне удалось сделать это, используя следующий код:
df1['telephone'] = df1['telephone'].astype(str)
df2["telephone"] = df2["telephone"].astype(str)
telephone_match = []
for telephone_1 in df1['telephone']:
telephone_found = False
for telephone_2 in df2["telephone"]:
if (telephone_2 in telephone_1):
telephone_match.append(telephone_2)
telephone_found = True
continue
if (not telephone_found):
telephone_match.append(False)
df1['matches'] = telephone_match
Это работает, но для запуска требуется много времени. Я почти уверен, что это самый глупый метод, но я понятия не имею, как сделать это эффективно. Может кто-нибудь помочь мне?






Вы можете определить функцию _find(), а затем apply() ее для df1["telephone"]:
Вы можете использовать set(), чтобы удалить дубликаты.
import pandas as pd
def _find(nums):
res = [num.strip() for num in nums.split(',')]
matches = [num for num in res if num in sdf2]
return matches[0] if matches else None
df1 = pd.DataFrame({
"telephone": ["115879878", "411564656", "465464654,45646546", "464665465,46456465,87972315", "123165648"]
})
df2 = pd.DataFrame({
"telephone": ["156465456", "132131321", "879878999", "456489798", "546489798", "465478978", "115879878"]
})
sdf2 = set(df2["telephone"])
df1["matches"] = df1["telephone"].apply(_find)
print(df1)
telephone matches
0 115879878 115879878
1 411564656 None
2 465464654,45646546 None
3 464665465,46456465,87972315 None
4 123165648 None
Вы можете сделать это немного более эффективным, используя генераторы:
import pandas as pd
def _find(nums):
gen = map(str.strip, nums.split(','))
return next((num for num in gen if num in sdf2), None)
df1 = pd.DataFrame({
"telephone": ["115879878", "411564656", "465464654,45646546", "464665465,46456465,87972315", "123165648"]
})
df2 = pd.DataFrame({
"telephone": ["156465456", "132131321", "879878999", "456489798", "546489798", "465478978", "115879878"]
})
sdf2 = set(df2["telephone"])
df1["matches"] = df1["telephone"].apply(_find)
print(df1)
Рассмотрим str.split и взрыв , чтобы сгладить несколько элементов, разделенных запятыми, в отдельных строках (где все остальные столбцы повторяются), а затем объединить со вторым фреймом данных в столбце telephone:
df3 = (
df1.assign(telephone = lambda x: x["telephone"].str.split(','))
.explode("telephone")
.merge(df2.assign(matched = True), on = "telephone", how = "left")
)
Если вам нужно сохранить исходную структуру df1, устраните дублирование приведенного выше результата с помощью некоторого уникального идентификатора и новых match столбцов, а затем merge вернитесь к исходному фрейму данных:
df3 = (
df3.reindex(["unique_id", "match"], axis = "columns")
.drop_duplicates()
)
df1 = df1.merge(df3, on = "unique_id", how = "left")
Другое возможное решение, которое начинается с объединения двух фреймов данных, затем находит дубликаты (которые являются совпадениями) и, наконец, удаляет дубликаты:
d = pd.concat([df1['telephone'].str.split(',').explode(), df2])
d.assign(matched = d.duplicated()).drop_duplicates(subset='telephone', keep='last')
Выход:
telephone matched
1 411564656 False
2 465464654 False
2 45646546 False
3 464665465 False
3 46456465 False
3 87972315 False
4 123165648 False
0 156465456 False
1 132131321 False
2 879878999 False
3 456489798 False
4 546489798 False
5 465478978 False
6 115879878 True
Вот однострочный подход:
df1["matches"] = df1['telephone'].str.split(',').explode().isin(df2['telephone']).groupby(level=0).agg(sum).astype(bool)
Предполагается, что тип столбца "telephone" — строка, как в вашем примере. Идея состоит в том, чтобы разделить каждое число split(','), затем сгладить explode(), затем найти вхождение isin(), а затем сгруппировать результаты по индексу.