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.
Вы можете 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.
Тем временем мы можем использовать обходной путь левого слияния, как показано выше.
левое соединение с dropna
, за которым следует drop_duplicates
, исправляет это
по этому поводу уже открыта ошибка: github.com/pandas-dev/pandas/issues/18776
либо это ошибка pandas - но внутреннее соединение, похоже, не соблюдает порядок (кажется, оно упорядочивается на основе порядка "вставки" левых клавиш) - вы можете видеть, что значение для
yx
должно бытьpr
, но это возвращаетсяrs