"Trop d'indexeurs" avec DataFrame.loc
J'ai lu les docs sur les segments un million de fois, mais n'ai jamais eu de ma tête autour de lui, donc je suis encore à essayer de comprendre comment utiliser loc
pour couper un DataFrame
avec un MultiIndex
.
Je vais commencer par le DataFrame
de cette SORTE de réponse:
value
first second third fourth
A0 B0 C1 D0 2
D1 3
C3 D0 6
D1 7
B1 C1 D0 10
D1 11
C3 D0 14
D1 15
A1 B0 C1 D0 18
D1 19
C3 D0 22
D1 23
B1 C1 D0 26
D1 27
C3 D0 30
D1 31
A2 B0 C1 D0 34
D1 35
C3 D0 38
D1 39
B1 C1 D0 42
D1 43
C3 D0 46
D1 47
A3 B0 C1 D0 50
D1 51
C3 D0 54
D1 55
B1 C1 D0 58
D1 59
C3 D0 62
D1 63
De sélectionner A0
et C1
valeurs, je peux le faire:
In [26]: df.loc['A0', :, 'C1', :]
Out[26]:
value
first second third fourth
A0 B0 C1 D0 2
D1 3
B1 C1 D0 10
D1 11
Qui travaille également choisir parmi trois niveaux, et même avec les tuples:
In [28]: df.loc['A0', :, ('C1', 'C2'), 'D1']
Out[28]:
value
first second third fourth
A0 B0 C1 D1 3
C2 D1 5
B1 C1 D1 11
C2 D1 13
Jusqu'à présent, brillant et intuitif.
Alors pourquoi ne puis-je pas sélectionner toutes les valeurs à partir du premier niveau de l'indice?
In [30]: df.loc[:, :, 'C1', :]
---------------------------------------------------------------------------
IndexingError Traceback (most recent call last)
<ipython-input-30-57b56108d941> in <module>()
----> 1 df.loc[:, :, 'C1', :]
/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in __getitem__(self, key)
1176 def __getitem__(self, key):
1177 if type(key) is tuple:
-> 1178 return self._getitem_tuple(key)
1179 else:
1180 return self._getitem_axis(key, axis=0)
/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in _getitem_tuple(self, tup)
694
695 # no multi-index, so validate all of the indexers
--> 696 self._has_valid_tuple(tup)
697
698 # ugly hack for GH #836
/usr/local/lib/python2.7/dist-packages/pandas/core/indexing.pyc in _has_valid_tuple(self, key)
125 for i, k in enumerate(key):
126 if i >= self.obj.ndim:
--> 127 raise IndexingError('Too many indexers')
128 if not self._has_valid_type(k, i):
129 raise ValueError("Location based indexing can only have [%s] "
IndexingError: Too many indexers
Ce n'est sûrement pas l'intention de comportement?
Note: je sais que c'est possible avec df.xs('C1', level='third')
mais le courant .loc
comportement semble incohérent.
source d'informationauteur LondonRob
Vous devez vous connecter pour publier un commentaire.
La raison pour laquelle cela ne fonctionne pas, est liée à la nécessité de définir l'axe de l'indexation (mentionné dans http://pandas.pydata.org/pandas-docs/stable/advanced.html). Une autre solution à votre problème est de simplement faire ceci:
Pandas se confond parfois, quand les indices sont similaires ou qui contiennent des valeurs similaires. Si vous avez une colonne nommée " C1 " ou quelque chose vous aussi, vous avez besoin de le faire en vertu de ce style de découpage/sélection.
Coffre-fort (dans le sens: cela fonctionne dans tous les cas), vous avez besoin d'index index de ligne et de colonnes, pour lequel vous pouvez utiliser
pd.IndexSlice
de le faire facilement:Ici
idx[:, :, 'C1', :]
est un moyen plus facile d'écrire[slice(None), slice(None),'C1', slice(None)]
. Au lieu depd.IndexSlice
vous pouvez également utilisernp.s_
qui est un peu plus courte.La raison que les autres le travail, je ne suis pas entièrement sûr de. Mais voir la note dans la documentation ici: http://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers (le premier rouge de la boîte de dialogue d'avertissement) où il est dit que: