Подтвердить что ты не робот

Объединение на одном уровне MultiIndex

Есть ли способ слияния на одном уровне MultiIndex без сброса индекса?

У меня есть "статическая" таблица значений времени-инварианта, индексированных ObjectID, и у меня есть "динамическая" таблица изменяющихся во времени полей, индексированных ObjectID + Date. Я хотел бы присоединиться к этим таблицам вместе.

Сейчас самое лучшее, что я могу придумать:

dynamic.reset_index().merge(static, left_on=['ObjectID'], right_index=True)

Однако динамическая таблица очень большая, и я не хочу, чтобы ее обманывали со своим индексом, чтобы объединить значения.

4b9b3361

Ответ 1

Да, поскольку pandas 0.14.0, теперь можно объединить однонаправленный DataFrame с уровнем многоиндексированного DataFrame с использованием .join.

df1.join(df2, how='inner') # how='outer' keeps all records from both data frames

В 0,14 pandas docs описывается это как эквивалентное, но больше оперативной памяти и быстрее, чем:

merge(df1.reset_index(),
      df2.reset_index(),
      on=['index1'],
      how='inner'
     ).set_index(['index1','index2'])

В документах также упоминается, что .join не может использоваться для объединения двух мультииндексированных DataFrames на одном уровне и из обсуждения трекера GitHub для предыдущей проблемы, похоже, что это не может быть приоритетным для реализации:

поэтому я объединился в одно соединение, см. # 6363; наряду с некоторыми документами по как сделать мульти-мульти-соединение. Это довольно сложно на самом деле воплощать в жизнь. и ИМХО не стоит усилий, поскольку он действительно не меняется использование/скорость использования памяти вообще.

Тем не менее, есть беседа GitHub об этом, где была некоторая недавняя разработка https://github.com/pydata/pandas/issues/6360. Это также возможно достичь путем сброса индексов, как упоминалось ранее и описанных в документах.

Ответ 2

Я обойду это, переиндексируя объединение данных, чтобы иметь полный мультииндекс, чтобы было возможно левое соединение.

# Create the left data frame
import pandas as pd
idx = pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[0,0,1,1],[0,1,0,1]], names=['lvl1','lvl2'])
df = pd.DataFrame([1,2,3,4],index=idx,columns=['data'])

#Create the factor to join to the data 'left data frame'
newFactor = pd.DataFrame(['fact:'+str(x) for x in df.index.levels[0]], index=df.index.levels[0], columns=['newFactor'])

Сделайте соединение в субиндексе, переиндексируя фрейм данных newFactor, чтобы содержать индекс левого фрейма данных

df.join(newFactor.reindex(df.index,level=0))

Ответ 3

Я бы использовал отображение для одного столбца:

df1['newcol'] = df1.index.get_level_values(-1).map(lambda x: df2.newcol[x])