pandas loc修改多索引dataFrame?

问题描述:

我发现了loc的一些有趣的行为(bug?),带有多索引数据帧,其中第一个索引是单个索引。使用loc(第一次)后,第一个索引(多索引)消失!pandas loc修改多索引dataFrame?

例如:

In [1]: import pandas as pd 

In [2]: x = pd.DataFrame({'idx1':[1]*10, 'idx2':[1]*5+[2]*5, 'idx3':range(5)+range(5), 'data': [1]*10}) 

In [3]: x = x.set_index(['idx1', 'idx2', 'idx3']).sortlevel() 

我的数据框:

In [5]: x.loc[1,:,:] 
Out[5]: 
      data 
idx2 idx3 
1 0  1 
    1  1 
    2  1 
    3  1 
    4  1 
2 0  1 
    1  1 
    2  1 
    3  1 
    4  1 

现在数据框中只有两个指标:

In [6]: x 
Out[6]: 
      data 
idx2 idx3 
1 0  1 
    1  1 
    2  1 
    3  1 
    4  1 
2 0  1 
    1  1 
    2  1 
    3  1 
    4  1 
用于第一次

In [4]: x 
Out[4]: 
       data 
idx1 idx2 idx3 
1 1 0  1 
      1  1 
      2  1 
      3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

这不会发生“IDX1”当有多个值:

In [7]: x = pd.DataFrame({'idx1':[1]*3+[2]*7, 'idx2':[1]*5+[2]*5, 'idx3':range(5)+range(5), 'data': [1]*10}) 

In [8]: x = x.set_index(['idx1', 'idx2', 'idx3']).sortlevel() 

In [9]: x 
Out[9]: 
       data 
idx1 idx2 idx3 
1 1 0  1 
      1  1 
      2  1 
2 1 3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

In [10]: x.loc[1,:,:] 
Out[10]: 
       data 
idx1 idx2 idx3 
1 1 0  1 
      1  1 
      2  1 

In [11]: x 
Out[11]: 
       data 
idx1 idx2 idx3 
1 1 0  1 
      1  1 
      2  1 
2 1 3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

这是正常的行为呢?如何避免这种情况?

Python 2.7版32位,熊猫== 0.16.2,numpy的== 1.11.1 + MKL

我认为更好的选择是与slicers,疗法它返回相同的输出 - 所有层面:

x = pd.DataFrame({'idx1':[1]*10, 'idx2':[1]*5+[2]*5, 'idx3':list(range(5))+list(range(5)), 'data': [1]*10}) 
x = x.set_index(['idx1', 'idx2', 'idx3']).sortlevel() 
print (x) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
      3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

idx = pd.IndexSlice 
print (x.loc[idx[1,:,:],:]) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
      3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

如果需要删除级别,使用xs与参数drop_level

print (x.xs(1, level=0, drop_level=True)) 
      data 
idx2 idx3  
1 0  1 
    1  1 
    2  1 
    3  1 
    4  1 
2 0  1 
    1  1 
    2  1 
    3  1 
    4  1 

print (x.xs(1, level=0, drop_level=False)) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
      3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

二样本:

x = pd.DataFrame({'idx1':[1]*3+[2]*7, 'idx2':[1]*5+[2]*5, 'idx3':list(range(5))+list(range(5)), 'data': [1]*10}) 

x = x.set_index(['idx1', 'idx2', 'idx3']).sortlevel() 
print (x) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
2 1 3  1 
      4  1 
    2 0  1 
      1  1 
      2  1 
      3  1 
      4  1 

idx = pd.IndexSlice 
print (x.loc[idx[1,:,:],:]) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
print (x.xs(1, level=0, drop_level=True)) 
      data 
idx2 idx3  
1 0  1 
    1  1 
    2  1 

print (x.xs(1, level=0, drop_level=False)) 
       data 
idx1 idx2 idx3  
1 1 0  1 
      1  1 
      2  1 
+0

非常感谢,现在它的工作! :) – jdzejdzej