https://pandas.pydata.org/docs/user_guide/merging.html#dataframe-join
Когда DataFrame объединяется с использованием только некоторых уровней MultiIndex, дополнительные уровни будут удалены из полученного соединения. Чтобы сохранить эти уровни, используйте DataFrame.reset_index() для имен этих уровней, чтобы переместить эти уровни в столбцы перед объединением.
Как следует понимать этот отрывок?
Выше упоминается пример соединения при использовании подмножества, где индекс --- 'num' все еще существует и транслируется. Мне это показалось странным. Если правый индекс не является подмножеством левого индекса, то он сообщит об ошибке, это пробовал, даже использование on для указания общего индекса не работает
In [109]: leftindex = pd.MultiIndex.from_product(
.....: [list("abc"), list("xy"), [1, 2]], names=["abc", "xy", "num"]
.....: )
.....:
In [110]: left = pd.DataFrame({"v1": range(12)}, index=leftindex)
In [111]: left
Out[111]:
v1
abc xy num
a x 1 0
2 1
y 1 2
2 3
b x 1 4
2 5
y 1 6
2 7
c x 1 8
2 9
y 1 10
2 11
In [112]: rightindex = pd.MultiIndex.from_product(
.....: [list("abc"), list("xy")], names=["abc", "xy"]
.....: )
.....:
In [113]: right = pd.DataFrame({"v2": [100 * i for i in range(1, 7)]}, index=rightindex)
In [114]: right
Out[114]:
v2
abc xy
a x 100
y 200
b x 300
y 400
c x 500
y 600
In [115]: left.join(right, on=["abc", "xy"], how = "inner")
Out[115]:
v1 v2
abc xy num
a x 1 0 100
2 1 100
y 1 2 200
2 3 200
b x 1 4 300
2 5 300
y 1 6 400
2 7 400
c x 1 8 500
2 9 500
y 1 10 600
2 11 600
Итак, как понимать этот отрывок?
Это применимо только при слиянии комбинации столбцов и уровней индекса.
Например, если мы расширим ваш пример и добавим столбец 'v1'
в right
, то merge
on=["abc", "xy", "v1"]
, в результате индекс 'num'
упадет:
# ...keeping all else unchanged
right = pd.DataFrame(
{"v1": range(1, 7), "v2": [100 * i for i in range(1, 7)]}, index=rightindex
)
left.merge(right, on=["abc", "xy", "v1"], how = "left")
v1 v2
abc xy
a x 0 NaN
x 1 100.0
y 2 200.0
y 3 NaN
b x 4 NaN
x 5 NaN
y 6 NaN
y 7 NaN
c x 8 NaN
x 9 NaN
y 10 NaN
y 11 NaN
Да, я ссылался на документы, но думаю, можно было бы сформулировать точнее. Однако ваш ответ уже работает хорошо.
Это предупреждение относится к merge
, а не join
.
join
Если вы не укажете on
, произойдет автоматическое выравнивание уровней с join
на общих уровнях и ни один уровень не будет понижен.
Давайте предположим немного более сложный пример, в котором элементы присутствуют на разных уровнях, чтобы лучше их оценить:
leftindex = pd.MultiIndex.from_product(
[list("abc"), list("xy"), [1, 2]], names=["abc", "xy", "num"]
)
left = pd.DataFrame({"v1": range(12)}, index=leftindex)
rightindex = pd.MultiIndex.from_product(
[list("abx"), list("cy"), list('z')], names=["xy", "abc", 'Z']
)
right = pd.DataFrame({"v2": [100 * i for i in range(1, 7)]}, index=rightindex)
left.join(right, how='inner')
# v1 v2
# abc xy num Z
# c x 1 z 8 500
# 2 z 9 500
Как видите, уровни были правильно выровнены по своему названию.
Если вы вручную передадите on
, то теперь join
будет полностью игнорировать названия уровней справа и принимать их по порядку:
left.join(right, on=['xy', 'abc'], how='inner')
# ValueError: len(left_on) must equal the number of levels in the index of "right"
left.join(right.droplevel('Z'), on=['abc', 'xy'], how='inner')
# v1 v2
# abc xy num
# a y 1 2 200
# 2 3 200
# b y 1 6 400
# 2 7 400
merge
Однако, если вы используете объединить, теперь лишние уровни в right
удаляются:
left.merge(right, left_index=True, right_index=True)
# v1 v2
# abc xy num
# c x 1 8 500
# 2 9 500
А если пройти on
, то сохраняются только общие уровни:
left.merge(right, on=["abc", "xy"], how = "inner")
# v1 v2
# abc xy
# c x 8 500
# x 9 500
Спасибо за отличный ответ, как вы сказали, дополнительные уровни удаляются из-за слияния. Другие методы я подсознательно не рассматривал. КвК
Я понимаю вашу точку зрения, но это
merge
здесь, и это также было бы верно, если бы выmerge
использовали только подмножество уровней без смеси столбцов (left.merge(right, on=["abc", "xy"], how = "inner")
)