#python #pandas #dataframe
Вопрос:
Я не могу понять, почему я получаю другое поведение для простого слияния в индексе обоих DFS. Основываясь на документах, я ожидаю, что результирующий фрейм данных будет соответствовать правильному индексу DF.
Случай 1
staff= pd.DataFrame([1,2,3],index=['Kelly','Sally','James'])
student= pd.DataFrame(['Texas','Califa','South Dakota'],index=['James','Mike','Sally'])
pd.merge(student,staff,left_index=True,right_index=True,how='right')
Я получаю:
0_x 0_y
Kelly NaN 22
Sally South Dakota 38
James Texas 45
который следует за правильным индексом DF (персонала)
Случай 2
left = pd.DataFrame( { "A": ["A0", "A1", "A2", "A3"], "B": ["B0", "B1", "B2", "B3"]},
index = ["K0", "K1", "K0", "K3"])
right = pd.DataFrame({"C": ["C0", "C1"], "D": ["D0", "D1"]}, index=["K1", "K0"])
pd.merge(left,right,left_index=True,right_index=True,how='right')
Я получаю
A B C D
K0 A0 B0 C1 D1
K0 A2 B2 C1 D1
K1 A1 B1 C0 D0
НО я ожидал, что:
A B C D
K1 A1 B1 C0 D0
K0 A0 B0 C1 D1
K0 A2 B2 C1 D1
как и в случае 1
Спасибо.
Ответ №1:
Проблема заключается в дублировании значений в индексе, что требует некоторых накладных расходов для позиционного различения строк с одним и тем же индексом. Этот процесс будет происходить независимо от типа merge
. Примечание join
также будет демонстрировать такое же поведение.
Чтобы обойти проблему , можно reset_index
объединить столбец "index"
в обоих кадрах, а затем set_index
в объединенном кадре, чтобы вернуть "index"
столбец в индекс кадра данных.
merged = pd.merge(
left.reset_index(), # Create Index Column on left
right.reset_index(), # Create Index Column on right
on='index', how='right'
).set_index('index').rename_axis(None) # Put index back
merged
:
A B C D
K1 A1 B1 C0 D0
K0 A0 B0 C1 D1
K0 A2 B2 C1 D1
Почему работает случай 1? Часть процесса выравнивания, которая вызывает «неожиданное» поведение, — это фаза, в которой используется позиционное упорядочение для различения разных строк с одним и тем же индексом.
Обратите внимание, что произойдет, если мы добавим повторяющееся значение индекса в первый пример. Повторяющиеся записи в столбце слияния требуют особого ухода.
staff = pd.DataFrame([1, 2, 3], index=['Sally', 'Sally', 'James'])
student = pd.DataFrame(['Texas', 'Califa', 'South Dakota'],
index=['James', 'Mike', 'Sally'])
staff
:
0
Sally 1 # Kelly Changed to Sally
Sally 2
James 3
Теперь merge
производит:
merged = pd.merge(student, staff, left_index=True, right_index=True,
how='right')
merged
:
0_x 0_y
James Texas 3
Sally South Dakota 1 # Sally is now grouped and sorted last
Sally South Dakota 2
Почему? Ну, при доступе к индексу в местоположении «Салли», какую Салли мы имеем в виду? И какое значение следует объединить? Этот вопрос решается путем сортировки и группировки значений, чтобы они отображались в порядке, и «Салли (1)» и «Салли (2)» можно различать как отдельные строки.
Опять же, этот процесс не происходит, когда значения индекса уникальны (поскольку нет необходимости в позиционной идентификации строк, поскольку они уже однозначно идентифицированы).
Почему обходной путь работает? Ну, значение столбца «Салли» при индексе 0 и значение столбца «Салли» и индекс 1 однозначно идентифицированы.
Комментарии:
1. Почему, однако, выравнивание индекса не происходит в Случае 1?
2. Выравнивание действительно происходит. На самом деле проблема заключается в части выравнивания «групповые ключи», которая вызывает проблему. взгляните на мое обновление
3. Генри, теперь все кликает с твоим обновленным комментарием. Мне любопытно, хотя откуда вы это знаете? Это связано с чтением исходного кода или с опытом работы с той же проблемой? Руководство пользователя явно не описывает это поведение. Я пытаюсь узнать больше о том, что происходит под капотом с Пандами. Спасибо.
4. И то, и другое? Я прочитал довольно много исходного кода. Но и по опыту. В данном случае это был исходный код. Слияние с этими не уникальными индексами в конечном итоге приведет к _join_non_unique . Вы можете заметить , что get_join_indexers имеет
sort=True
независимо от того, как была задана сортировка при первоначальном слиянии. В итоге вы получитеleft_index [0, 2, 1]
и правильный индекс[1, 1, 0]
.
Ответ №2:
В соответствии с документацией https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.merge.html pd.merge имеет возможность передать сортировку в аргументе , который сортирует ключ соединения, как в вашем, — это индекс.
staff= pd.DataFrame([1,2,3],index=['Kelly','Sally','James'])
student= pd.DataFrame(['Texas','Califa','South Dakota'],index=
['James','Mike','Sally'])
pd.merge(student,staff,left_index=True,right_index=True,how='right', sort=True)
0_x 0_y
James Texas 3
Kelly NaN 1
Sally South Dakota 2
вы также можете использовать индекс сортировки
left = pd.DataFrame( { "A": ["A0", "A1", "A2", "A3"], "B": ["B0", "B1", "B2", "B3"]},
index = ["K0", "K1", "K0", "K3"])
right = pd.DataFrame({"C": ["C0", "C1"], "D": ["D0", "D1"]}, index=["K1", "K0"])
pd.merge(left,right,left_index=True,right_index=True,how='right').sort_index(ascending=True)
A B C D
K1 A1 B1 C0 D0
K0 A0 B0 C1 D1
K0 A2 B2 C1 D1