web-dev-qa-db-fra.com

en choisissant parmi multi-index pandas

J'ai un cadre de données multi-index avec les colonnes 'A' et 'B'.

Existe-t-il un moyen de sélectionner des lignes en filtrant une colonne du multi-index sans réinitialiser l'index à un seul index de colonne?

Par exemple.

# has multi-index (A,B)
df
#can I do this? I know this doesn't work because the index is multi-index so I need to     specify a Tuple

df.ix[df.A ==1]
73
silencer

Une solution consiste à utiliser le get_level_values Méthode d'indexation:

In [11]: df
Out[11]:
     0
A B
1 4  1
2 5  2
3 6  3

In [12]: df.iloc[df.index.get_level_values('A') == 1]
Out[12]:
     0
A B
1 4  1

En 0.13, vous pourrez utiliser xs avec drop_level argument :

df.xs(1, level='A', drop_level=False) # axis=1 if columns

Remarque: s'il s'agissait d'une colonne MultiIndex plutôt que d'un index, vous pourriez utiliser la même technique:

In [21]: df1 = df.T

In [22]: df1.iloc[:, df1.columns.get_level_values('A') == 1]
Out[22]:
A  1
B  4
0  1
110
Andy Hayden

Vous pouvez aussi utiliser query qui est très lisible à mon avis et facile à utiliser:

import pandas as pd

df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [10, 20, 50, 80], 'C': [6, 7, 8, 9]})
df = df.set_index(['A', 'B'])

      C
A B    
1 10  6
2 20  7
3 50  8
4 80  9

Pour ce que vous aviez en tête, vous pouvez maintenant simplement faire:

df.query('A == 1')

      C
A B    
1 10  6

Vous pouvez également avoir des requêtes plus complexes en utilisant and

df.query('A >= 1 and B >= 50')

      C
A B    
3 50  8
4 80  9

et or

df.query('A == 1 or B >= 50')

      C
A B    
1 10  6
3 50  8
4 80  9

Vous pouvez également interroger différents niveaux d’index , par exemple.

df.query('A == 1 or C >= 8')

reviendra

      C
A B    
1 10  6
3 50  8
4 80  9

Si vous souhaitez utiliser des variables dans votre requête, vous pouvez utiliser @ :

b_threshold = 20
c_threshold = 8

df.query('B >= @b_threshold and C <= @c_threshold')

      C
A B    
2 20  7
3 50  8
26
Cleb

Vous pouvez utiliser DataFrame.xs():

In [36]: df = DataFrame(np.random.randn(10, 4))

In [37]: df.columns = [np.random.choice(['a', 'b'], size=4).tolist(), np.random.choice(['c', 'd'], size=4)]

In [38]: df.columns.names = ['A', 'B']

In [39]: df
Out[39]:
A      b             a
B      d      d      d      d
0 -1.406  0.548 -0.635  0.576
1 -0.212 -0.583  1.012 -1.377
2  0.951 -0.349 -0.477 -1.230
3  0.451 -0.168  0.949  0.545
4 -0.362 -0.855  1.676 -2.881
5  1.283  1.027  0.085 -1.282
6  0.583 -1.406  0.327 -0.146
7 -0.518 -0.480  0.139  0.851
8 -0.030 -0.630 -1.534  0.534
9  0.246 -1.558 -1.885 -1.543

In [40]: df.xs('a', level='A', axis=1)
Out[40]:
B      d      d
0 -0.635  0.576
1  1.012 -1.377
2 -0.477 -1.230
3  0.949  0.545
4  1.676 -2.881
5  0.085 -1.282
6  0.327 -0.146
7  0.139  0.851
8 -1.534  0.534
9 -1.885 -1.543

Si vous souhaitez conserver le niveau A (le mot clé drop_level N'est disponible qu'à partir de la v0.13.0):

In [42]: df.xs('a', level='A', axis=1, drop_level=False)
Out[42]:
A      a
B      d      d
0 -0.635  0.576
1  1.012 -1.377
2 -0.477 -1.230
3  0.949  0.545
4  1.676 -2.881
5  0.085 -1.282
6  0.327 -0.146
7  0.139  0.851
8 -1.534  0.534
9 -1.885 -1.543
26
Phillip Cloud

Vous pouvez utiliser DataFrame.loc :

>>> df.loc[1]

Exemple

>>> print(df)
       result
A B C        
1 1 1       6
    2       9
  2 1       8
    2      11
2 1 1       7
    2      10
  2 1       9
    2      12

>>> print(df.loc[1])
     result
B C        
1 1       6
  2       9
2 1       8
  2      11

>>> print(df.loc[2, 1])
   result
C        
1       7
2      10
3
umn

Une autre option est:

filter1 = df.index.get_level_values('A') == 1
filter2 = df.index.get_level_values('B') == 4

df.iloc[filter1 & filter2]
Out[11]:
     0
A B
1 4  1
1
Gonzalo Goral