将“缺失”的多级索引行插入Pandas数据框中

7

我有一个带有两级多重索引的pandas DataFrame。第二个级别是数字,对于每个唯一的第一级别索引值,它应该被排序和顺序化,但存在间隔。如何插入“缺失”的行?示例输入:

import pandas as pd
df = pd.DataFrame(list(range(5)),
                  index=pd.MultiIndex.from_tuples([('A',1), ('A',3),
                                                   ('B',2), ('B',3), ('B',6)]),
                  columns='value')
#     value
#A 1      0
#  3      1
#B 2      2
#  3      3
#  6      4

期望输出:

#     value
#A 1      0
#  2    NaN
#  3      1
#B 2      2
#  3      3
#  4    NaN
#  5    NaN
#  6      4

我猜我可以使用resample,但我无法将数字转换为任何日期格式。


1
通过for循环创建索引,然后重新索引它? - BENY
@Wen-Ben 谢谢!那将是我的最后选择。我不喜欢在 pandas 中使用循环。 - DYZ
4个回答

2
如果有意愿,就有办法。我不为此感到自豪,但我认为这种方法是有效的。
尝试:
def f(x):
    levels = x.index.remove_unused_levels().levels
    x = x.reindex(pd.MultiIndex.from_product([levels[0], np.arange(levels[1][0], levels[1][-1]+1)]))
    return x

df.groupby(level=0, as_index=False, group_keys=False).apply(f)

输出:

     value
A 1    0.0
  2    NaN
  3    1.0
B 2    2.0
  3    3.0
  4    NaN
  5    NaN
  6    4.0

2

经过深思熟虑,我终于自己想出了一个解决方案。从这个方案的糟糕程度来看,我所面临的问题并不是非常典型的。

new_index = d.index.to_frame()\
                .groupby(0)[1]\
                .apply(lambda x:
                         pd.Series(1, index=range(x.min(), x.max() + 1))).index
d.reindex(new_index)

1
您可以根据缺失的索引使用以下内容:
result.unstack(1).stack(0, dropna=False).fillna(0)

当你取消堆叠时,pandas会将df扩展为行和列,在上面的例子中,第一级索引将成为列名。然后,再次堆叠,将df返回到其原始形式,但是这次需要确保使用dropna=False,以便NaN值在缺失索引时存在。最后,使用.fillna(0)是可选的,取决于您想要如何处理NaN值。

这也会创建(B, 1),而这不在所需的数据框中。它也没有插入新值(B, 4)(B, 5) - FirefoxMetzger

0

口味因人而异,但我认为回归到列表推导式可以使代码稍微更易读:

df.reindex(
    pd.MultiIndex.from_tuples([
        (level_0, level_1)
        for level_0 in df.reset_index(0).level_0.unique()
        for level_1 in range(
            df.reset_index(1).loc[level_0, "level_1"].min(),
            df.reset_index(1).loc[level_0, "level_1"].max()+1
        )
]))

# Output:
#value
#A  1   0.0
#   2   NaN
#   3   1.0
#B  2   2.0
#   3   3.0
#   4   NaN
#   5   NaN
#   6   4.0

虽然这当然比采用apply方法慢:

list-comprehension: 2.57 ms ± 19 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
DYZ apply: 1.25 ms ± 8.75 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Scott's apply: 2.19 ms ± 9.84 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接