如何切片具有MultiIndex索引和MultiIndex列的Pandas DataFrame?

时间:2019-12-04 07:36:09

标签: python dataframe

我正在寻找一个与基于Silicon的设备A和B的结果相对应的新DataFrame。

以下是我用于创建DataFrame的代码:

import numpy as np
import pandas as pd

x = np.array(
    [
        [0.26, 0.92, 0.05, 0.43],
        [1.00, 0.62, 1.00, 1.00],
        [1.00, 0.97, 0.04, 1.00],
        [0.00, 1.00, 1.00, 0.88],
        [1.00, 1.00, 1.00, 0.79],
        [0.98, 1.00, 0.79, 0.99],
        [0.99, 1.00, 1.00, 1.00],
        [0.18, 1.00, 0.26, 1.00],
        [0.22, 0.00, 0.34, 0.82],
    ]
)
rowIndx = pd.MultiIndex.from_product(
    [["Slurm", "Zoidberg", "Wernstrom"], ["A", "B", "C"]],
    names=["Laboratory", "Device"],
)
colIndex = pd.MultiIndex.from_product(
    [["Replicant 1 ", "Replicant 2 "], ["Silicon", "Carbon"]]
)
robot = pd.DataFrame(data=x, index=rowIndx, columns=colIndex)
robot

这是桌子的图像。 Picture of data

这是我认为可以使用的代码,但是它给了我错误,所以现在我不知道该怎么做, robot[(robot.Device=="A") & (robot.Device=="B")][["Silicon"]]

3 个答案:

答案 0 :(得分:2)

我认为您想要这样的东西:

In [6]: robot.loc[:, (robot.columns.get_level_values(level=1)=='Silicon')]
Out[6]:
                  Replicant 1  Replicant 2
                       Silicon      Silicon
Laboratory Device
Slurm      A              0.26         0.05
           B              1.00         1.00
           C              1.00         0.04
Zoidberg   A              0.00         1.00
           B              1.00         1.00
           C              0.98         0.79
Wernstrom  A              0.99         1.00
           B              0.18         0.26
           C              0.22         0.34

这里有两个关键点:第一个关键点是使用robot.loc[ _ , _ ](指定两个参数,一个用于索引,一个用于列)。这必须是您的MultiIndex类型索引和MultiIndex类型列可以理解的东西。

第二个键是robots.columns.get_level_values(level=1),它获取DataFrame图像中显示的4列的1级(碳/硅)的4列标签:

In [7]: robot.columns.get_level_values(level=1)
Out[7]: Index(['Silicon', 'Carbon', 'Silicon', 'Carbon'], dtype='object')

,然后根据给定条件过滤要显示的列:

In [8]: robot.columns.get_level_values(level=1)=='Silicon'
Out[8]: array([ True, False,  True, False])

如果除了Silicon之外还有其他元素,可以这样使用|运算符(而不是&运算符):

robot.loc[:, (robot.columns.get_level_values(level=1)=='Silicon')|(robot.columns.get_level_values(level=1)=='Carbon')]

或更短:

lv = robot.columns.get_level_values(level=1)
robot.loc[:, (lv=='Silicon')|(lv=='Carbon')]

更新:如果您还想过滤索引中的值,则可以使用robot.index.get_level_values()代替robot.columns.get_level_values()。这是一个示例:

lv = robot.columns.get_level_values(level=1)
ilv = robot.index.get_level_values(level=1)
robot.loc[(ilv=='A')|(ilv=='B'), (lv=='Silicon')]

我们已经用逻辑掩码替换了:(这意味着MultiIndex的所有级别的所有值)来过滤索引,就像过滤列一样。

答案 1 :(得分:1)

您的数据框为MultiIndex,因此您需要使用以下代码选择一行:

result = robot.iloc[(robot.index.get_level_values('Device') == 'A')|(robot.index.get_level_values('Device') == 'B')]

现在,如果只希望列Silicon使用以下代码:

result.iloc[:, result.columns.get_level_values(1)== "Silicon"]

答案 2 :(得分:1)

像这样使用slicers

robot.loc[(slice(None), ['A', 'B']), (slice(None), 'Silicon')]

                  Replicant 1  Replicant 2 
                       Silicon      Silicon
Laboratory Device                          
Slurm      A              0.26         0.05
           B              1.00         1.00
Zoidberg   A              0.00         1.00
           B              1.00         1.00
Wernstrom  A              0.99         1.00
           B              0.18         0.26

或:

idx = pd.IndexSlice
robot.loc[idx[:, ['A', 'B']], idx[:, 'Silicon']]