Как я могу объединить два кадра данных на основе столбца списков в Pandas

import pandas as pd

Воспроизводимая установка

У меня есть два фрейма данных:

df=\
pd.DataFrame.from_dict({'A':['xy','yx','zy','zz'],
                        'B':[[1, 3],[4, 3, 5],[3],[2, 6]]})

df2=\
pd.DataFrame.from_dict({'B':[1,3,4,5,6],
                        'C':['pq','rs','pr','qs','sp']})

df выглядит так:

    A          B
0  xy     [1, 3]
1  yx  [4, 3, 5]
2  zy        [3]
3  zz     [2, 6]

df2 выглядит так:

   B   C
0  1  pq
1  3  rs
2  4  pr
3  5  qs
4  6  sp

Цель

Я хотел бы объединить эти два, чтобы сформировать res:

res=\
pd.DataFrame.from_dict({'A':['xy','yx','zy','zz'],
                        'C':['pq','pr','rs','sp']})

то есть

    A   C
0  xy  pq
1  yx  pr
2  zy  rs
3  zz  sp

Строка с xy в df имеет lsit [1,3]. Есть строка со значением 1 в столбце B в df2. Столбец C имеет значение pq в этой строке, поэтому я комбинирую xy с pq. То же самое для следующих двух рядов. Последняя строка: нет значения с 2 в столбце B в df2, поэтому я выбираю значение 6 (последняя строка в df содержит список [2,6]).


Вопрос

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


A very similar post in Spanish SO, which inspired this post.

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
0
387
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы можете explode "B" в отдельные строки, затем объединить на "B" и удалить дубликаты.

Большое спасибо Asish M. в комментариях за указание на возможную ошибку при заказе.

(df.explode('B')
   .merge(df2, on='B', how='left')
   .dropna(subset=['C'])
   .drop_duplicates('A'))

    A  B   C
0  xy  1  pq
2  yx  4  pr
5  zy  3  rs
7  zz  6  sp

В идеале должно было работать следующее:

df.explode('B').merge(df2).drop_duplicates('A')

Однако pandas (на момент написания, версия 1.2dev) не сохраняет порядок левых клавиш при слиянии, что является ошибкой, см. GH18776.

Тем временем мы можем использовать обходной путь левого слияния, как показано выше.

либо это ошибка pandas - но внутреннее соединение, похоже, не соблюдает порядок (кажется, оно упорядочивается на основе порядка "вставки" левых клавиш) - вы можете видеть, что значение для yx должно быть pr, но это возвращается rs

Asish M. 25.12.2020 02:12

левое соединение с dropna, за которым следует drop_duplicates, исправляет это

Asish M. 25.12.2020 02:12

по этому поводу уже открыта ошибка: github.com/pandas-dev/pandas/issues/18776

Asish M. 25.12.2020 02:19

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