Я использую combine_first
для объединения двух DataFrames на основе двух ключей, цель состоит в том, чтобы добавить индексы df2, которые не содержатся в df1 к результату, и перезаписать индексы, которые содержатся в обоих значениях из df2.
Пример df1:
df1 = pd.DataFrame({
"key1": ["A", "A", "A", "B", "B", "C", "C"],
"id": ["a1", "a2", "a3", 1, 2, "c1", "c2"],
"data1": [pd.np.random.randint(5) for i in range(7)],
"data2": [pd.np.random.randint(1000) for i in range(7)]
})
Пример df2:
df2 = pd.DataFrame({
"key1": ["B", "B", "B"],
"id": [2, 3, 4],
"data1": [pd.np.random.randint(5) for i in range(3)],
"data2": [pd.np.random.randint(1000) for i in range(3)]
})
df1.set_index(["key1", "id"]).combine_first(df2.set_index(["key1", "id"]))
дает желаемый результат:
data1 data2
key1 id
A a1 0.0 588.0
a2 2.0 709.0
a3 3.0 877.0
B 1 3.0 468.0
2 0.0 612.0
3 2.0 139.0
4 3.0 154.0
C c1 4.0 855.0
c2 4.0 564.0
Однако после сохранения результата в виде csv, снова загрузив его и запустив ту же команду, я получаю следующую ошибку:
TypeError: '<' not supported between instances of 'str' and 'int'
Но только для df2, где id
- только int
. Когда id
содержит символы, он работает без проблем.
Я нашел это в документах Pandas:
Другая операция индексирования может потенциально изменить dtype серии.
Это объясняет, почему проблема сохраняется, если я изменяю dtype df2.id
на object
перед установкой индекса и объединением. Как я могу конкретно установить dtype уровня MultiIndex, чтобы комбинация работала?
EDIT Чтобы еще раз проиллюстрировать проблему:
df = df1.set_index(["key1", "id"]).combine_first(df2.set_index(["key1", "id"]))
df.to_csv("tests/combtest2.csv", sep=";")
df_loaded = pd.read_csv("tests/combtest2.csv", sep=";", index_col=["key1", "id"])
Выглядит хорошо:
data1 data2
key1 id
A a1 0.0 588.0
a2 2.0 709.0
a3 3.0 877.0
B 1 3.0 468.0
2 0.0 612.0
3 2.0 139.0
4 3.0 154.0
C c1 4.0 855.0
c2 4.0 564.0
Но df_loaded.combine_first(df2.set_index(["key1", "id"]))
приводит к:
data1 data2
key1 id
A a1 0.0 588.0
a2 2.0 709.0
a3 3.0 877.0
B 1 3.0 468.0
2 0.0 612.0
3 2.0 139.0
4 3.0 154.0
C c1 4.0 855.0
c2 4.0 564.0
B 2 2.0 317.0
3 2.0 139.0
4 3.0 154.0
Перед объединением вы должны преобразовать столбец id
в str
, а не object
.
Это будет работать:
df2.id = df2.id.astype(str)
df_loaded.combine_first(df2.set_index(["key1", "id"]))
key1
а затем добавил их, чтобы получить окончательный результат. Я бы предпочел не включать этот дополнительный шаг, а просто установить для level (1) dtype дляdf2
значение object.dtype
df2.id
наobject
перед установкой индекса и объединением не решает проблему? Я только что попробовал, и это сработало.