J'ai une trame de données multi-index avec les colonnes «A» et «B».
Existe-t-il un moyen de sélectionner des lignes en filtrant sur 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]
python
pandas
dataframe
multi-index
silencieux
la source
la source
Réponses:
Une façon consiste à utiliser la
get_level_values
méthode Index: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
avecdrop_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 pouvez 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
la source
Vous pouvez également utiliser
query
ce qui est très lisible à mon avis et simple à 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
la source
df.query('A == 1 or C >= 8')
df.query()
fonctionne très bien avec les variables si elles sont référencées avec un «@» dans l'expression dans la requête, par exempledf.query('A == @var
) pour une variablevar
dans l'environnement.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
A
niveau (l'drop_level
argument mot - clé 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
la source
Comprendre comment accéder aux pandas multi-indexés DataFrame peut vous aider dans toutes sortes de tâches comme celle-là.
Copiez-collez ceci dans votre code pour générer un exemple:
# hierarchical indices and columns index = pd.MultiIndex.from_product([[2013, 2014], [1, 2]], names=['year', 'visit']) columns = pd.MultiIndex.from_product([['Bob', 'Guido', 'Sue'], ['HR', 'Temp']], names=['subject', 'type']) # mock some data data = np.round(np.random.randn(4, 6), 1) data[:, ::2] *= 10 data += 37 # create the DataFrame health_data = pd.DataFrame(data, index=index, columns=columns) health_data
Vous donnera une table comme celle-ci:
Accès standard par colonne
health_data['Bob'] type HR Temp year visit 2013 1 22.0 38.6 2 52.0 38.3 2014 1 30.0 38.9 2 31.0 37.3 health_data['Bob']['HR'] year visit 2013 1 22.0 2 52.0 2014 1 30.0 2 31.0 Name: HR, dtype: float64 # filtering by column/subcolumn - your case: health_data['Bob']['HR']==22 year visit 2013 1 True 2 False 2014 1 False 2 False health_data['Bob']['HR'][2013] visit 1 22.0 2 52.0 Name: HR, dtype: float64 health_data['Bob']['HR'][2013][1] 22.0
Accès par ligne
health_data.loc[2013] subject Bob Guido Sue type HR Temp HR Temp HR Temp visit 1 22.0 38.6 40.0 38.9 53.0 37.5 2 52.0 38.3 42.0 34.6 30.0 37.7 health_data.loc[2013,1] subject type Bob HR 22.0 Temp 38.6 Guido HR 40.0 Temp 38.9 Sue HR 53.0 Temp 37.5 Name: (2013, 1), dtype: float64 health_data.loc[2013,1]['Bob'] type HR 22.0 Temp 38.6 Name: (2013, 1), dtype: float64 health_data.loc[2013,1]['Bob']['HR'] 22.0
Tranchage multi-index
idx=pd.IndexSlice health_data.loc[idx[:,1], idx[:,'HR']] subject Bob Guido Sue type HR HR HR year visit 2013 1 22.0 40.0 53.0 2014 1 30.0 52.0 45.0
la source
ValueError: cannot handle a non-unique multi-index!
erreurVous 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
la source
df.loc[0], df.loc[1]....df.loc[n]
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
la source