【问题标题】:Pandas: partial indexing on multiIndex dataframe doesn't duplicate rowsPandas:multiIndex 数据帧上的部分索引不会重复行
【发布时间】:2020-09-04 07:17:00
【问题描述】:

我正在尝试使用 .loc 索引,使用标签列表从两级 pandas MultiIndex 数据框中选择行(包括重复)。

但是,如果我尝试使用 MultiIndex 数据帧进行这种类型的索引,则输出的行顺序与输入相同,并且重复的索引将被忽略。这是一个例子:

import numpy as np
import pandas as pd
import string as s

index1 = list(s.ascii_uppercase[:4])
index2 = np.arange(2)
col_names='col1 col2 col3'.split()

new_slices = list('DDAB') # note order and repition of labels

multi_index = pd.MultiIndex.from_product([index1,index2],names=["level0","level1"])

data = np.arange(len(index1)*len(index2)*len(col_names))
data=data.reshape(len(index1)*len(index2),-1)


df2 = pd.DataFrame(data,columns=col_names,index=multi_index)

print(df2.loc[new_slices])

               col1  col2  col3
level0 level1                  
A      0          0     1     2
       1          3     4     5
B      0          6     7     8
       1          9    10    11
D      0         18    19    20
       1         21    22    23

我希望:

               col1  col2  col3
level0 level1                  
D      0         18    19    20
       1         21    22    23
D      0         18    19    20
       1         21    22    23
A      0          0     1     2
       1          3     4     5
B      0          6     7     8
       1          9    10    11

是否有我错过的 MultiIndex 特定功能? 还是我误解了 MultiIndex 中的级别是如何工作的?

(但是,当从“常规”数据框中进行选择时,这正如我所期望的那样工作,例如:)

import numpy as np
import pandas as pd
import string as s

index1 = list(s.ascii_uppercase[:4])
col_names='col1 col2 col3'.split()

new_slices = list('DDAB') # note order and repition of labels

data1 = np.arange(len(index1)*len(col_names)).reshape(len(index1),-1)
df1 = pd.DataFrame(data1,columns=col_names,index=index1)

print(df1)
print(df1.loc[new_slices])

这给出了我期望的结果——一个包含 D、D、A、B 行的数据框。

【问题讨论】:

    标签: python pandas multi-index


    【解决方案1】:

    这样试试

    index1 = list(s.ascii_uppercase[:4])
    index2 = np.arange(2)
    col_names='col1 col2 col3'.split()
    
    new_slices = list('DDAB') # note order and repition of labels
    
    multi_index = pd.MultiIndex.from_product([index1,index2],names=["level0","level1"])
    
    data = np.arange(len(index1)*len(index2)*len(col_names))
    data=data.reshape(len(index1)*len(index2),-1)
    
    
    df2 = pd.DataFrame(data,columns=col_names,index=multi_index)
    df2.unstack().loc[new_slices].stack() # <=== this does the trick
    

    【讨论】:

    • 巧妙使用stack/unstack!
    • @PaulH 对不起...我指的是帖子的作者
    【解决方案2】:

    你没有错过任何东西。这是 pandas 实现索引的方式的结果。部分索引不会复制行,只有完整的索引。

    部分:仅第一级中的两个:

    df2.loc[['A', 'A']]
    
                   col1  col2  col3
    level0 level1                  
    A      0          0     1     2
           1          3     4     5
    

    部分:仅第二级中的两个:

    df2.loc[(slice(None), [0, 0]), :]
    
                   col1  col2  col3
    level0 level1                  
    A      0          0     1     2
    B      0          6     7     8
    C      0         12    13    14
    D      0         18    19    20
    

    但是,完整的索引会重复行:

    df2.loc[[('A', 0),('A', 0)]]
    
                   col1  col2  col3
    level0 level1                  
    A      0          0     1     2
           0          0     1     2
    

    这是对单个索引进行索引复制行的特定情况的一般情况。单个索引上的所有索引都是完整的,因为只有一个级别。

    如果你想通过索引获取重复行,而不是通过连接或连接,你可以像这样构建一个完整的索引列表:

    complete = [(first, second) for first in new_slices for second in set(df2.index.get_level_values(1))]
    df2.loc[complete]
    
                   col1  col2  col3
    level0 level1                  
    D      0         18    19    20
           1         21    22    23
           0         18    19    20
           1         21    22    23
    A      0          0     1     2
           1          3     4     5
    B      0          6     7     8
           1          9    10    11
    

    【讨论】:

    • 太棒了!感谢您的详细解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 2019-08-12
    • 2020-04-22
    • 2023-01-12
    • 1970-01-01
    • 2014-04-28
    • 2020-01-06
    相关资源
    最近更新 更多