在特定的 MultiIndex 将一个 DataFrame 附加到另一个 DataFrame

Appending a DataFrame to another DataFrame, at a specific MultiIndex

下面DataFrame,即df1

In[0]: df1
Out[0]:
                     A         B
first second                    
bar   one     1.764052  0.400157
      one     0.978738  2.240893
      one     1.867558 -0.977278
      two     0.950088 -0.151357

我希望在 MultiIndex ('bar','one') 的最后一行 之后追加另一个 DataFrame ,同时给新添加的行 相同的 MultiIndex.

也就是下面的df2

In[1]: df2
Out[1]:

                     A         B
first second                    
baz   three  -0.103219  0.410599
      three   0.144044  1.454274

期望的结果是:

                     A         B
first second                    
bar   one     1.764052  0.400157
      one     0.978738  2.240893
      one     1.867558 -0.977278
      one    -0.103219  0.410599   # there 2 rows
      one     0.144044  1.454274   #    arrived from df2
      two     0.950088 -0.151357

问题到此为止。

我前面的一些失败尝试:

(1) 按组迭代(使用 groupby)并根据 df2 值连接一个新的 DataFrame:

for idx, data in df1.groupby(level=[0,1]):
    df1.loc[idx] = pd.concat([data, pd.DataFrame(df2, index=idx)], ignore_index=True)

Exception: cannot handle a non-unique multi-index!

(也尝试将它们放在新的 DataFrame 中)。

(2) reindexing df2 优先:

for idx, data in df1.groupby(level=[0,1]):
    df2.reindex(idx)

Exception: cannot handle a non-unique multi-index!

或:

for idx, data in df1.groupby(level=[0,1]):
    df2.index = idx
    break

            A         B
bar -0.103219  0.410599
one  0.144044  1.454274

如果您想手动将数据插入现有数据框,您需要决定几件事。

  1. 你要把它插在哪里?我通过找到索引为 ('bar', 'one').
  2. 的第一个实例来解决这个问题
  3. 你打算怎么称呼这些数据?换句话说,您要插入的数据的索引是什么?显然,您正在更改索引值。您必须提前知道这些索引值是什么。除非你想让它继承它前面一行的索引值(我也会展示这个)。

position = (df1.index.to_series() == ('bar', 'two')).values.argmax()

pd.concat([
        df1.iloc[:position],
        df2.set_index([['bar', 'bar'], ['one', 'one']]),
        df1.iloc[position:]
    ])


新行从前一行继承索引值的示例(结果与上面相同)

position = (df1.index.to_series() == ('bar', 'two')).values.argmax()
insert_idx = pd.MultiIndex.from_tuples(df1.index[[position - 1]].tolist() * len(df2))

pd.concat([
        df1.iloc[:position],
        df2.set_index(insert_idx),
        df1.iloc[position:]
    ])