Внутреннее слияние двух DataFrames при частичном совпадении строки

У нас есть следующие два фрейма данных

temp = pd.DataFrame(np.array([['I am feeling very well',1],['It is hard to believe this happened',0],
                                  ['What is love?',1], ['No new friends',0],
                             ['I love this show',1],['Amazing day today',1]]),
                                columns = ['message','sentiment'])

temp_truncated = pd.DataFrame(np.array([['I am feeling very',1],['It is hard to believe',1],
                                  ['What is',1], ['Amazing day',1]]),
                                columns = ['message','cutoff'])

Моя идея состоит в том, чтобы создать третий DataFrame, который будет представлять внутреннее соединение между temp и temp_truncated, находя совпадения в temp, которые начинаются с/содержат строки в temp_truncated

Желаемый результат:

     message                             sentiment   cutoff            
0    I am feeling very well               1          1
1    It is hard to believe this happened  0          1
2    What is love                         1          1
3    Amazing day today                    1          1

Ваш вывод не полностью соответствует предоставленным данным;)

mozway 23.11.2022 15:33

@mozway Я только что понял, что использовал другой образец. Зафиксированный. Глядя в решение.

DarknessPlusPlus 23.11.2022 15:34
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
2
52
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете использовать:

import re
pattern = '|'.join(map(re.escape, temp_truncated['message']))

key = temp['message'].str.extract(f'({pattern})', expand=False)

out = (temp
 .merge(temp_truncated.rename(columns = {'message': 'sub'}),
        left_on=key, right_on='sub')
 .drop(columns='sub')
)

Вывод:

                               message sentiment cutoff
0               I am feeling very well         1      1
1  It is hard to believe this happened         0      1
2                        What is love?         1      1
3                    Amazing day today         1      1

Вот подход, использующий rapidfuzz с pandas.merge:

#pip install rapidfuzz
from rapidfuzz import process

out = (
        temp_truncated
           .assign(message_adapted = (temp_truncated['message']
                                       .map(lambda x: process.extractOne(x, temp['message']))).str[0])
           .merge(temp, left_on = "message_adapted", right_on = "message", how = "left", suffixes=("_", ""))
           .drop(columns=["message_adapted", "message_"])
           .loc[:, temp.columns.tolist() + ["cutoff"]]
      )

# Вывод :

print(out)
                               message sentiment cutoff
0               I am feeling very well         1      1
1  It is hard to believe this happened         0      1
2                        What is love?         1      1
3                    Amazing day today         1      1

Обратите внимание, что нечеткое сопоставление и сопоставление подстрок — это не одно и то же. Если вы замените Amazing Day на Amazing Job в temp_truncated, это все равно будет соответствовать (вероятно, не должно)

mozway 23.11.2022 15:52

Для меня не было никакой разницы, особенно когда я получил точный ожидаемый результат от OP. Я удалю свой ответ, большое спасибо, mozway;)

Timeless 23.11.2022 15:58

Вам не нужно удалять, это все равно приятно, но важно, чтобы разница была понятна ;)

mozway 23.11.2022 16:01

@abokey нет, пожалуйста, продолжайте отвечать, так как комментарий о том, чем нечеткое сопоставление отличается от фактического сопоставления, важен и должен оставаться здесь для дальнейшего использования.

DarknessPlusPlus 23.11.2022 16:01

Вы можете использовать str.startswith или другие функции str., такие как str.contains, в приложении для получения кадра данных совпадений:

matches = temp_truncated.message.apply(
    lambda x: temp[temp.message.str.startswith(x)]['sentiment']
).dropna(how='all')

Этот фрейм данных matches содержит строки temp_truncated, которые совпадают с одной из строк в temp. Эти temp строки являются столбцами matches фрейма данных. Значения — это значения тональности этих temp строк. При этом вы можете отфильтровать фрейм данных temp только совпавшими строками, а затем обогатить его соответствующим значением отсечки из temp_truncated:

df = temp.iloc[matches.columns]
df.index = matches.index
df = df.merge(temp_truncated['cutoff'], left_index=True, right_index=True)

Результат соответствует желаемому результату:

    message                             sentiment   cutoff
0   I am feeling very well              1           1
1   It is hard to believe this happened 0           1
2   What is love?                       1           1
3   Amazing day today                   1           1

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