web-dev-qa-db-fra.com

Obtenir la première ligne de la structure de données dans les pandas Python en fonction de critères

Disons que j'ai un dataframe comme celui-ci

import pandas as pd
df = pd.DataFrame([[1, 2, 1], [1, 3, 2], [4, 6, 3], [4, 3, 4], [5, 4, 5]], columns=['A', 'B', 'C'])

>> df
   A  B  C
0  1  2  1
1  1  3  2
2  4  6  3
3  4  3  4
4  5  4  5

La table d'origine est plus compliquée avec plus de colonnes et de lignes.

Je veux obtenir la première ligne qui remplit certains critères. Exemples:

  1. Obtenir la première ligne où A> 3 (retourne la ligne 2)
  2. Obtenir la première ligne où A> 4 ET B> 3 (retourne la ligne 4)
  3. Obtenir la première ligne où A> 3 ET (B> 3 OR C> 2) (retourne la ligne 2)

Mais, si aucune ligne ne remplit les critères, je souhaite obtenir la première après la trier par ordre décroissant selon A (ou les autres cas selon B, C, etc.)

  1. Obtenir la première ligne où A> 6 (retourne la ligne 4 en la classant par A desc et obtenir la première)

J'ai pu le faire en itérant sur la base de données (je sais que craps: P). Donc, je préfère un moyen plus pythonique de le résoudre.

18
Tasos

Ce tutoriel est très bon pour le tranchage de pandas. Assurez-vous de vérifier. Sur certains extraits ... Pour découper une image de données avec une condition, vous utilisez ce format:

>>> df[condition]

Cela retournera une tranche de votre cadre de données que vous pouvez indexer à l'aide de iloc. Voici vos exemples:

  1. Obtenir la première ligne où A> 3 (retourne la ligne 2)

    >>> df[df.A > 3].iloc[0]
    A    4
    B    6
    C    3
    Name: 2, dtype: int64
    

Si ce que vous voulez réellement est le numéro de ligne, plutôt que d'utiliser iloc, ce serait df[df.A > 3].index[0].

  1. Obtenez la première rangée où A> 4 ET B> 3:

    >>> df[(df.A > 4) & (df.B > 3)].iloc[0]
    A    5
    B    4
    C    5
    Name: 4, dtype: int64
    
  2. Obtenir la première ligne où A> 3 ET (B> 3 OR C> 2) (retourne la ligne 2)

    >>> df[(df.A > 3) & ((df.B > 3) | (df.C > 2))].iloc[0]
    A    4
    B    6
    C    3
    Name: 2, dtype: int64
    

Maintenant, avec votre dernier cas, nous pouvons écrire une fonction qui gère le cas par défaut de retourner le cadre trié par ordre décroissant:

>>> def series_or_default(X, condition, default_col, ascending=False):
...     sliced = X[condition]
...     if sliced.shape[0] == 0:
...         return X.sort_values(default_col, ascending=ascending).iloc[0]
...     return sliced.iloc[0]
>>> 
>>> series_or_default(df, df.A > 6, 'A')
A    5
B    4
C    5
Name: 4, dtype: int64

Comme prévu, il retourne à la ligne 4.

28
Tgsmith61591

Pour les correspondances existantes, utilisez query:

df.query(' A > 3' ).head(1)
Out[33]: 
   A  B  C
2  4  6  3

df.query(' A > 4 and B > 3' ).head(1)
Out[34]: 
   A  B  C
4  5  4  5

df.query(' A > 3 and (B > 3 or C > 2)' ).head(1)
Out[35]: 
   A  B  C
2  4  6  3
9
Boud