Exemple de code:
In [171]: A = np.array([1.1, 1.1, 3.3, 3.3, 5.5, 6.6])
In [172]: B = np.array([111, 222, 222, 333, 333, 777])
In [173]: C = randint(10, 99, 6)
In [174]: df = pd.DataFrame(Zip(A, B, C), columns=['A', 'B', 'C'])
In [175]: df.set_index(['A', 'B'], inplace=True)
In [176]: df
Out[176]:
C
A B
1.1 111 20
222 31
3.3 222 24
333 65
5.5 333 22
6.6 777 74
Maintenant, je veux récupérer les valeurs A:
Q1: dans l'intervalle [3.3, 6.6] - valeur de retour attendu: [3.3, 5.5, 6.6] ou [3.3, 3.3, 5.5, 6.6] en dernier lieu inclus, et [ 3.3, 5.5] ou [3.3, 3.3, 5.5] sinon.
Q2: dans l'intervalle [2.0, 4.0] - valeur de retour attendu: [3.3] ou [3.3, 3.3]
Idem pour toute autre dimension MultiIndex , par exemple les valeurs B:
Q: dans la plage [111, 500] avec répétitions, en nombre de lignes de données dans la plage - valeur de retour attendue: [111, 222, 222, 333, 333]
Plus formel:
Supposons que T est un tableau avec les colonnes A, B et C. Le tableau comprend n lignes. Les cellules de tableau sont des nombres, par exemple des entiers doubles A, B et C. Créons un DataFrame de la table T, appelons-le DF. Définissons les index des colonnes A et B de DF (sans duplication, c.-à-d. Pas de colonnes séparées A et B en tant qu’index et séparées en tant que données), c’est-à-dire A et B dans ce cas MultiIndex .
Des questions:
Je connais les réponses aux questions ci-dessus dans le cas de colonnes qui ne sont pas des index, mais dans le cas des index, après une longue recherche sur le Web et une expérimentation des fonctionnalités de pandas , je n'ai pas réussi. La seule méthode (sans programmation supplémentaire) que je vois maintenant est d’avoir un duplicata de A et B en tant que colonnes de données en plus d’index.
Pour interroger les df par les valeurs MultiIndex, par exemple, où (A> 1,7) et (B <666):
In [536]: result_df = df.loc[(df.index.get_level_values('A') > 1.7) & (df.index.get_level_values('B') < 666)]
In [537]: result_df
Out[537]:
C
A B
3.3 222 43
333 59
5.5 333 56
Par conséquent, pour obtenir par exemple les 'A' valeurs d'index, si toujours requis:
In [538]: result_df.index.get_level_values('A')
Out[538]: Index([3.3, 3.3, 5.5], dtype=object)
Le problème est que, dans le cas de données volumineuses, les performances de par index sont 10% plus mauvaises que la sélection des lignes régulières triées. Et dans le travail répétitif, en boucle, le retard accumulé. Voir exemple:
In [558]: df = store.select(STORE_EXTENT_BURSTS_DF_KEY)
In [559]: len(df)
Out[559]: 12857
In [560]: df.sort(inplace=True)
In [561]: df_without_index = df.reset_index()
In [562]: %timeit df.loc[(df.index.get_level_values('END_TIME') > 358200) & (df.index.get_level_values('START_TIME') < 361680)]
1000 loops, best of 3: 562 µs per loop
In [563]: %timeit df_without_index[(df_without_index.END_TIME > 358200) & (df_without_index.START_TIME < 361680)]
1000 loops, best of 3: 507 µs per loop
Pour une meilleure lisibilité , nous pouvons simplement utiliser la query()
Méthode , afin d'éviter la longue fonction df.index.get_level_values()
et reset_index
/set_index
aller et venir.
Voici la cible DataFrame
:
In [12]: df
Out[12]:
C
A B
1.1 111 68
222 40
3.3 222 20
333 11
5.5 333 80
6.6 777 51
Réponse pour Q1 (A
dans la plage [3.3, 6.6]
):
In [13]: df.query('3.3 <= A <= 6.6') # for closed interval
Out[13]:
C
A B
3.3 222 20
333 11
5.5 333 80
6.6 777 51
In [14]: df.query('3.3 < A < 6.6') # for open interval
Out[14]:
C
A B
5.5 333 80
et bien sûr, on peut jouer avec <, <=, >, >=
pour tout type d'inclusion.
De même, répondez pour Q2 (A
dans la plage [2.0, 4.0]
):
In [15]: df.query('2.0 <= A <= 4.0')
Out[15]:
C
A B
3.3 222 20
333 11
Réponse pour Q3 (B
dans la plage [111, 500]
):
In [16]: df.query('111 <= B <= 500')
Out[16]:
C
A B
1.1 111 68
222 40
3.3 222 20
333 11
5.5 333 80
Et en plus, vous pouvez [~ # ~] combiner [~ # ~] la requête pour col A
et B
très naturellement!
In [17]: df.query('0 < A < 4 and 150 < B < 400')
Out[17]:
C
A B
1.1 222 40
3.3 222 20
333 11
Avec un index "float", vous voulez toujours l'utiliser comme une colonne plutôt que comme une action d'indexation directe. Celles-ci fonctionneront toutes, que les terminaux existent ou non.
In [11]: df
Out[11]:
C
A B
1.1 111 81
222 45
3.3 222 98
333 13
5.5 333 89
6.6 777 98
In [12]: x = df.reset_index()
Q1
In [13]: x.loc[(x.A>=3.3)&(x.A<=6.6)]
Out[13]:
A B C
2 3.3 222 98
3 3.3 333 13
4 5.5 333 89
5 6.6 777 98
Q2
In [14]: x.loc[(x.A>=2.0)&(x.A<=4.0)]
Out[14]:
A B C
2 3.3 222 98
3 3.3 333 13
Q3
In [15]: x.loc[(x.B>=111.0)&(x.B<=500.0)]
Out[15]:
A B C
0 1.1 111 81
1 1.1 222 45
2 3.3 222 98
3 3.3 333 13
4 5.5 333 89
Si vous souhaitez récupérer les index, définissez-les simplement. C'est une opération peu coûteuse.
In [16]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B'])
Out[16]:
C
A B
1.1 111 81
222 45
3.3 222 98
333 13
5.5 333 89
Si vous voulez VRAIMENT les valeurs d'index réelles
In [5]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B']).index
Out[5]:
MultiIndex
[(1.1, 111), (1.1, 222), (3.3, 222), (3.3, 333), (5.5, 333)]