Как извлечь подстроку из столбца в фрейме данных на основе столбца из другого фрейма данных?

Я нашел решение своей проблемы, но оно явно самое тупое и неэффективное. Я надеялся, что кто-нибудь сможет помочь мне с правильным решением.

У меня есть два фрейма данных, содержащие столбец с номером телефона. 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

Это работает, но для запуска требуется много времени. Я почти уверен, что это самый глупый метод, но я понятия не имею, как сделать это эффективно. Может кто-нибудь помочь мне?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
63
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

  • Вы можете определить функцию _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(), а затем сгруппировать результаты по индексу.

Другие вопросы по теме

Вывод Python DataFrame.info не отражает удаленные строки
Графическая карта не отображает данные GeoJSON правильно – возможная проблема с геометрией или картографированием
Не удалось преобразовать число с плавающей запятой 64 в число с плавающей запятой 32 в Python
Как получить несколько показателей для каждой категории в кросс-таблице панд?
Как очистить таблицу csv, содержащуюся внутри кнопки JavaScript, с помощью Python?
Функция модели ARMA для будущих невидимых данных с датами начала и окончания?
Я продолжаю получать ошибку «функция не повторяется» с фильтром Pandas DataFrame, но та же функция работает с применением. Что мне не хватает?
Эффективный поиск значения столбца в столбце, содержащем списки, с помощью pandas
Сортировка месяцев внутри объекта Multi index groupby
Объединить/объединить несколько фреймов данных pandas со смешиванием значений в одном столбце