使用 .loc 与来自具有 MultIndex 的 DataFrame 的级别子集

问题描述 投票:0回答:2

给定一个具有 3 个级别的多索引的数据框:

import pandas as pd

df = pd.concat({'a': pd.Series([1,2,3,1]),
                'b': pd.Series([5,4,3,5]),
                'c': pd.Series(range(9,13)),
                'd': pd.Series(range(13,17))}, axis=1).set_index(['a', 'b', 'c'])
>>>         d
    a b c       
    1 5 9   13
    2 6 10  14
    3 7 11  15
    4 8 12  16

我想将 loc 与前 2 个级别的索引列表一起使用:

idx = pd.MultiIndex.from_arrays([[1, 2], [5, 4]], names=('a', 'b'))
>>> MultiIndex([(1, 5),
                (2, 6)],
               names=['a', 'b'])

我尝试将 .loc 与单独的索引一起使用:

df.loc[idx[0]]
>>>      d
    c     
    9   13
    12  16

df.loc[idx[1]]
>>>      d
    c     
    10  14

我期望

df.loc[idx]
返回与

相同的结果
pd.concat([df.loc[i] for i in idx])
>>>     d
    c     
    9   13
    12  16
    10  14

但是我

df.loc[idx]
回来了

ValueError: operands could not be broadcast together with shapes (2,2) (3,) (2,2)

有没有比

pd.concat([df.loc[i] for i in idx])
更干净的东西来获得预期的结果?

python pandas indexing multi-index
2个回答
0
投票

要使用

loc
和多索引数据帧前 2 个级别的索引列表来实现所需的结果,您可以使用
pd.IndexSlice
。这是一个例子:

import pandas as pd

df = pd.concat({'a': pd.Series([1, 2, 3, 1]),
                'b': pd.Series([5, 4, 3, 5]),
                'c': pd.Series(range(9, 13)),
                'd': pd.Series(range(13, 17))}, axis=1).set_index(['a', 'b', 'c'])

idx = pd.MultiIndex.from_arrays([[1, 2], [5, 4]], names=('a', 'b'))

# Use pd.IndexSlice to slice the first two levels of the MultiIndex
idx_slice = pd.IndexSlice[:, :]

# Use loc with the sliced MultiIndex
result = df.loc[idx_slice, :].loc[idx, :]

print(result)


0
投票

loc
具有 MultiIndex 需要相同的级别,解决方法可能是将额外的级别暂时设置为列:

levels = df.index.names.difference(idx.names)

out = df.reset_index(levels).loc[idx].set_index(levels, append=True)

join

out = df.join(pd.DataFrame(index=idx), how='right')

输出:

         d
a b c     
1 5 9   13
    12  16
2 4 10  14
© www.soinside.com 2019 - 2024. All rights reserved.