2016-10-28 6 views
1

Я нашел какое-то интересное поведение (ошибка?) Loc, с мультииндексированным фреймом данных, где первый индекс является одиночным. После использования 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() 

Мой dataFrame:

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 

LOC используется впервые:

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 

Теперь DataFrame имеет только два индекса:

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 

Это не происходит, когда «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 

Является ли это нормальное поведение? Как этого избежать?

питона 2,7 32bit, панды == 0.16.2, 1.11.1 NumPy == + MKL

ответ

2

Я думаю, что лучше выбрать с slicers, þér его возвращать тот же результат - все уровни:

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

Смежные вопросы