如何插入MultiIndex DataFrame的特定位置?

时间:2017-08-10 09:45:58

标签: python pandas

假设我有一个pandas DataFrame,它在结构上看起来类似于以下内容。然而在 实践它可能会大得多,1级索引的数量,以及2级索引(每1级索引)的数量会有所不同,所以解决方案不应该对此做出假设:

index = pandas.MultiIndex.from_tuples([
    ("a", "s"),
    ("a", "u"),
    ("a", "v"),
    ("b", "s"),
    ("b", "u")])

result = pandas.DataFrame([
    [1, 2],
    [3, 4],
    [5, 6],
    [7, 8],
    [9, 10]], index=index, columns=["x", "y"])

看起来像这样:

      x   y
a s   1   2
  u   3   4
  v   5   6
b s   7   8
  u   9  10

现在让我们说我想为每个“a”和“b”级别创建一个“总”行。所以考虑到上面的输入,我希望我的代码产生这样的东西:

      x   y
a s   1   2
  u   3   4
  v   5   6
  t   9  12
b s   7   8
  u   9  10
b t  16  18

这是我到目前为止的代码:

# Calculate totals
for level, _ in result.groupby(level=0):

    # work out the global total for that desk:
    x_sum = result.loc[level]["x"].sum()
    y_sum = result.loc[level]["y"].sum()

    result = result.append(pandas.DataFrame([[x_sum, y_sum]], columns=result.columns, index=pandas.MultiIndex.from_tuples([(level, "t")])))

但这会导致“总”列附加到结尾:

      x   y
a s   1   2
  u   3   4
  v   5   6
b s   7   8
  u   9  10
a t   9  12
b t  16  18

使用result.sort_index()排序并不能达到我想要的效果:

      x   y
a s   1   2
  t   9  12
  u   3   4
  v   5   6
b s   7   8
  t  16  18
  u   9  10

我做错了什么?

1 个答案:

答案 0 :(得分:2)

这真的令人生气,但sorted Multiindex的原因是性能更好。此外,如果未按MultiIndex排序,则MultiIndex可能需要按df = result.groupby(level=0).sum() df.index = [df.index, ['t'] * len(df.index)] df1 = pd.concat([result, df]).sort_index().reindex(['s','u','t'], level=1) df1 = pd.concat([result, df]).sort_index() print (df1) x y a s 1 2 t 4 6 u 3 4 b s 5 6 t 12 14 u 7 8 df1 = df1.reindex(['s','u','t'], level=1) print (df1) x y a s 1 2 u 3 4 t 4 6 b s 5 6 u 7 8 t 12 14 进行选择。

但如果真的需要更改标签的位置,可以使用UnsortedIndexError

print (result.index.get_level_values(1).unique().tolist())
['s', 'u']

df1 = df1.reindex(result.index.get_level_values(1).unique().tolist() + ['t'], level=1)
print (df1)
      x   y
a s   1   2
  u   3   4
  t   4   6
b s   5   6
  u   7   8
  t  12  14

更动态的解决方案:

def f(x):
    x.loc[(x.name, 't'),:] = x.sum()
    return x   

df = result.groupby(level=0, group_keys=False).apply(f)
print (df)
        x     y
a s   1.0   2.0
  u   3.0   4.0
  t   4.0   6.0
b s   5.0   6.0
  u   7.0   8.0
  t  12.0  14.0

使用reindex自定义函数setting with enlargement的另一个解决方案:

<a data-toggle="modal" href="login.aspx#myModal">Forgot Password?</a>