2017-09-07 3 views
3

Warum gibt .loc nur eine einzelne Zeile zurück, wo mehrere Zeilen die gleiche MultiIndex haben?Inkonsistenz zwischen Pandas xs und loc für wiederholte Indizes

die folgenden Datenrahmen

  col0  col1 col2 
idx0 idx1 
0 0  1.0 example1 1.0 
    0  4.0 example2 8.0 
    1  9.0 example3 27.0 
    1  16.0 example4 64.0 
1 0  0.5 example1 0.5 
    0  2.0 example2 4.0 
    1  4.5 example3 13.5 
    1  8.0 example4 32.0 

die .xs Beim Betrieb

In [121]: df.xs((0,1), level=[0,1]) 
Out[121]: 
      col0  col1 col2 
idx0 idx1 
0 1  9.0 example3 27.0 
    1  16.0 example4 64.0 

während der .loc Betrieb wählt

In [125]: df.loc[[(0,1)]] 
Out[125]: 
      col0  col1 col2 
idx0 idx1 
0 1  16.0 example4 64.0 

Dies markiert ist noch weiter durch die folgende

wählen wird
In [149]: df.loc[pd.IndexSlice[:, 1], :] 
Out[149]: 
      col0  col1 col2 
idx0 idx1 
0 1  9.0 example3 27.0 
    1  16.0 example4 64.0 

In [150]: df.loc[pd.IndexSlice[0, 1], :] 
Out[150]: 
col0   16 
col1 example4 
col2   64 
Name: (0, 1), dtype: object 

Set Up

import pandas as pd 
import numpy as np 
idx0 = range(2) 
idx1 = np.repeat(range(2), 2) 

midx = pd.MultiIndex(
    levels=[idx0, idx1], 
    labels=[ 
     np.repeat(range(len(idx0)), len(idx1)), 
     np.tile(range(len(idx1)), len(idx0)) 
    ], 
    names=['idx0', 'idx1'] 
) 

df = pd.DataFrame(
    [ 
     [i**2/float(j), 'example{}'.format(i), i**3/float(j)] 
     for j in range(1, len(idx0) + 1) 
     for i in range(1, len(idx1) + 1) 
    ], 
    columns=['col0', 'col1', 'col2'], 
    index=midx 
) 
+1

Dies ist besonders ungewöhnlich gegeben, dass [mit einem Basisindex, 'loc' zurückkehren alle Instanzen des Labels, wenn du Duplikate hast.] (https://stackoverflow.com/a/45636490/7954504) –

+1

FYI: Wenn du den Index mit 'np.array' als' dtype = int' initiierst, dann immer noch hat Probleme, so ist es kein Problem mit Gleitkomma –

+1

Welche Version von Pandas verwenden Sie? – Alexander

Antwort

1

Mit .xs

df.xs((0,1), level=[0,1]) 
Out[74]: 
      col0  col1 col2 
idx0 idx1      
0 1  9.0 example3 27.0 
    1  16.0 example4 64.0 

Mit .loc

df.loc[0].loc[1] 
Out[75]: 
     col0  col1 col2 
idx1      
1  9.0 example3 27.0 
1  16.0 example4 64.0 

[] im Sekundärindex hinzufügen: (PS: link)

df.loc[(0, [1]),:] 

Out[90]: 
      col0  col1 col2 
idx0 idx1      
0 1  9.0 example3 27.0 
    1  16.0 example4 64.0 
+0

Dies beantwortet die Frage nicht wirklich ... Ich habe einen Workaround, ich frage, warum '.loc [[(0,1)]]' nicht funktioniert. Ich danke Ihnen für Ihr weiteres Beispiel, obwohl dies scheinbar nur das unerwartete Verhalten von '.loc [[(0,1)]]' betont! –

+0

@AlexanderMcFarlane I aktualisiert, sry, morgen ... Weißt du .. – Wen

+2

können Sie erklären, warum die '[1]' notwendig ist? Es scheint ziemlich willkürlich! –

1

Ich glaube nicht, dass Ihr Multi-Index korrekt erstellt wird.

df = df.assign(
    idx0=[0] * 4 + [1] * 4, 
    idx1=[0, 0, 1, 1] * 2).set_index(['idx0', 'idx1']) 

eine der richtigen Art und Weise verwendet loc für den Zugriff auf die Daten zu verwenden:

>>> df.loc[(0, 1), :] 
      col0  col1 col2 
idx0 idx1      
0 1  9 example3 27 
    1  16 example4 64 

den gleichen Befehl auf dem ursprünglichen Datenrahmen verwenden, erhalte ich: TypeError: only integer arrays with one element can be converted to an index.

UPDATE

Wie ich schon erwähnt, scheinen Sie nicht Ihre Multi-Index korrekt zu erzeugen. Dieser Datenrahmen mit dem richtig konstruierten Multi-Index funktioniert wie erwartet mit Ihren Beispielen (mit älteren Pandas, v 0.17.2).

midx = pd.MultiIndex.from_product([[0, 1], [0, 0, 1, 1]], names=['idx0', 'idx1']) 
df = pd.DataFrame(
    [ 
     [i**2/float(j), 'example{}'.format(i), i**3/float(j)] 
     for j in range(1, len(idx0) + 1) 
     for i in range(1, len(idx1) + 1) 
    ], 
    columns=['col0', 'col1', 'col2'], 
    index=midx) 

midx wie oben definiert:

>>> midx 
MultiIndex(levels=[[0, 1], [0, 1]], 
      labels=[[0, 0, 0, 0, 1, 1, 1, 1], [0, 0, 1, 1, 0, 0, 1, 1]], 
      names=[u'idx0', u'idx1']) 

Mit midx pro Ihre Definition:

>>> midx 
MultiIndex(levels=[[0, 1], [0, 0, 1, 1]], 
      labels=[[0, 0, 0, 0, 1, 1, 1, 1], [0, 1, 2, 3, 0, 1, 2, 3]], 
      names=[u'idx0', u'idx1']) 
+0

hinzufügen. Das 'df' in der Frage hat zwei' int64' Indizes, es scheint, als wäre es "richtig" erstellt worden. Kannst du erklären, warum sich das bei der Änderung wie erwartet verhält? –

+0

ja ich bin auf das selbe gestoßen. Ich werde meine 'MultiIndex'-Erstellung in dem Beispiel unten sauberer machen. Ich verdichtete es, um meinen Beitrag kürzer zu machen, aber ich habe die gleiche Verwirrung wie @BradSolomon –

+0

Danke für das Update. Handelt es sich bei diesem Problem um doppelte Werte in den 'levels' kwarg? Es scheint, dass die Pandas-Bibliothek möglicherweise einen Fehler ausgibt, wenn "Ebenen" keine Duplikate enthalten können? –

Verwandte Themen