550 votes

Filtre les lignes du cadre de données si la valeur de la colonne est dans une liste de valeurs définie.

J'ai un DataFrame Python pandas. rpt :

rpt
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231')
Data columns:
STK_ID                    47518  non-null values
STK_Name                  47518  non-null values
RPT_Date                  47518  non-null values
sales                     47518  non-null values

Je peux filtrer les lignes dont l'identifiant d'action est '600809' comme ça : rpt[rpt['STK_ID'] == '600809']

<class 'pandas.core.frame.DataFrame'>
MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331')
Data columns:
STK_ID                    25  non-null values
STK_Name                  25  non-null values
RPT_Date                  25  non-null values
sales                     25  non-null values

et je veux obtenir toutes les lignes de certains stocks ensemble, tels que ['600809','600141','600329'] . Cela signifie que je veux une syntaxe comme celle-ci :

stk_list = ['600809','600141','600329']

rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas 

Puisque pandas n'accepte pas la commande ci-dessus, comment atteindre l'objectif ?

0 votes

stk_list = ['600809', '600141', '600329'] result=filter(lambda item : item in stk_list,df['STK_ID']) vous pouvez utiliser le filtre pour obtenir une liste d'éléments itérables.

799voto

BrenBarn Points 63718

Utilisez le isin méthode :

rpt[rpt['STK_ID'].isin(stk_list)]

29 votes

Et pour la négation de ceci, quelle serait la manière correcte de procéder à un !isin() ?

143 votes

@dbyte : Vous utilisez simplement le ~ opérateur : rpt[~rpt['STK_ID'].isin(stk_list)]

0 votes

Existe-t-il un moyen direct de faire cela sur un seul niveau d'un multi-index (c'est-à-dire sans le reset_index ?).

126voto

ajcr Points 4047

isin() est idéal si vous avez une liste de correspondances exactes, mais si vous avez une liste de correspondances partielles ou de sous-chaînes à rechercher, vous pouvez filtrer en utilisant la fonction str.contains et les expressions régulières.

Par exemple, si nous voulons renvoyer un DataFrame où tous les ID d'actions qui commencent par '600' et sont ensuite suivis de trois chiffres quelconques :

>>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]{3}$')] # ^ means start of string
...   STK_ID   ...                                    # [0-9]{3} means any three digits
...  '600809'  ...                                    # $ means end of string
...  '600141'  ...
...  '600329'  ...
...      ...   ...

Supposons maintenant que nous avons une liste de chaînes de caractères dont nous voulons les valeurs dans 'STK_ID' pour terminer par, par exemple

endstrings = ['01$', '02$', '05$']

Nous pouvons joindre ces chaînes de caractères avec le caractère regex 'ou'. | et passer la chaîne à str.contains pour filtrer le DataFrame :

>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
...   STK_ID   ...
...  '155905'  ...
...  '633101'  ...
...  '210302'  ...
...      ...   ...

Enfin, contains peut ignorer le cas (en définissant case=False ), ce qui vous permet d'être plus général lorsque vous spécifiez les chaînes de caractères que vous voulez faire correspondre.

Par exemple,

str.contains('pandas', case=False)

correspondrait à PANDAS , PanDAs , paNdAs123 et ainsi de suite.

0 votes

Merci pour cela, la recherche regex serait très utile. Même si isin ne fonctionne que pour un appariement parfait, il accepte dataframes , Series , Index etc. @jakevdp a fourni une excellente solution ici, qui consiste à extraire les valeurs correspondantes de df1 étant donné une autre trame de données df2 : stackoverflow.com/a/33282617/4752883 . Dans mon cas, j'ai un df2 mais les valeurs dans df2 ne seront pas des correspondances exactes, donc je me demande s'il y a un moyen d'utiliser regex sur isin (ou une autre fonction), similaire à ce que vous avez indiqué ici ?

47voto

yemu Points 1054

vous pouvez également utiliser des plages en utilisant :

b = df[(df['a'] > 1) & (df['a'] < 5)]

46voto

bscan Points 1472

Vous pouvez aussi directement requête votre DataFrame pour cette information.

rpt.query('STK_ID in (600809,600141,600329)')

Ou bien, de la même manière, recherchez des gammes :

rpt.query('60000 < STK_ID < 70000')

33voto

firelynx Points 56

Découpage des données avec pandas

Étant donné un cadre de données comme celui-ci :

    RPT_Date  STK_ID STK_Name  sales
0 1980-01-01       0   Arthur      0
1 1980-01-02       1    Beate      4
2 1980-01-03       2    Cecil      2
3 1980-01-04       3     Dana      8
4 1980-01-05       4     Eric      4
5 1980-01-06       5    Fidel      5
6 1980-01-07       6   George      4
7 1980-01-08       7     Hans      7
8 1980-01-09       8   Ingrid      7
9 1980-01-10       9    Jones      4

Il existe plusieurs façons de sélectionner ou de découper les données.

Utilisation de .isin

Le plus évident est le .isin fonctionnalité. Vous pouvez créer un masque qui vous donne une série de True / False qui peuvent être appliquées à un cadre de données comme ceci :

mask = df['STK_ID'].isin([4, 2, 6])

mask
0    False
1    False
2     True
3    False
4     True
5    False
6     True
7    False
8    False
9    False
Name: STK_ID, dtype: bool

df[mask]
    RPT_Date  STK_ID STK_Name  sales
2 1980-01-03       2    Cecil      2
4 1980-01-05       4     Eric      4
6 1980-01-07       6   George      4

Le masquage est la solution ad hoc au problème, mais il n'est pas toujours performant en termes de vitesse et de mémoire.

Avec l'indexation

En plaçant l'index sur le STK_ID nous pouvons utiliser l'objet de découpage intégré de Pandas. .loc

df.set_index('STK_ID', inplace=True)
         RPT_Date STK_Name  sales
STK_ID                           
0      1980-01-01   Arthur      0
1      1980-01-02    Beate      4
2      1980-01-03    Cecil      2
3      1980-01-04     Dana      8
4      1980-01-05     Eric      4
5      1980-01-06    Fidel      5
6      1980-01-07   George      4
7      1980-01-08     Hans      7
8      1980-01-09   Ingrid      7
9      1980-01-10    Jones      4

df.loc[[4, 2, 6]]
         RPT_Date STK_Name  sales
STK_ID                           
4      1980-01-05     Eric      4
2      1980-01-03    Cecil      2
6      1980-01-07   George      4

C'est la façon la plus rapide de procéder, même si l'indexation peut prendre un peu de temps, cela permet de gagner du temps si vous souhaitez effectuer plusieurs requêtes de ce type.

Fusion des cadres de données

Cela peut également être fait en fusionnant les cadres de données. Cela conviendrait mieux à un scénario dans lequel vous avez beaucoup plus de données que dans ces exemples.

stkid_df = pd.DataFrame({"STK_ID": [4,2,6]})
df.merge(stkid_df, on='STK_ID')
   STK_ID   RPT_Date STK_Name  sales
0       2 1980-01-03    Cecil      2
1       4 1980-01-05     Eric      4
2       6 1980-01-07   George      4

Note

Toutes les méthodes ci-dessus fonctionnent même s'il y a plusieurs lignes avec le même nom. 'STK_ID'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X