Filtre dataframe lignes si la valeur dans la colonne est dans une liste de valeurs
j'ai une 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 le stock id est '600809'
comme ceci: 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 réunir toutes les rangées de certains stocks, comme ['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 au-dessus du commandement, comment atteindre l'objectif?
7 réponses
utilisez la méthode isin
. rpt[rpt['STK_ID'].isin(stk_list)]
.
isin()
est idéal si vous avez une liste de correspondances exactes, mais si vous avez une liste de correspondances partielles ou de substrats à rechercher, vous pouvez filtrer en utilisant la méthode str.contains
et des expressions régulières.
par exemple, si nous voulons retourner une base de données où tous les numéros d'identification de stock qui commencent par '600'
et sont ensuite suivis de n'importe quels trois chiffres:
>>> 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 que nous voulons que les valeurs de 'STK_ID'
se terminent par, par exemple
endstrings = ['01$', '02$', '05$']
nous pouvons joindre ces chaînes avec le caractère regex ' ou ' |
et passer la chaîne à str.contains
pour filtrer la base de données:
>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
... STK_ID ...
... '155905' ...
... '633101' ...
... '210302' ...
... ... ...
enfin, contains
peut ignorer case (en définissant case=False
), vous permettant d'être plus général en spécifiant les chaînes que vous voulez associer.
par exemple,
str.contains('pandas', case=False)
correspondrait PANDAS
, PanDAs
, paNdAs123
, et ainsi de suite.
vous pouvez également utiliser des gammes en utilisant:
b = df[(df['a'] > 1) & (df['a'] < 5)]
découpage de données avec pandas
avec une base de données comme celle-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.
en utilisant .isin
la caractéristique la plus évidente est .isin
. Vous pouvez créer un masque qui vous donne une série de déclarations True
/ False
, qui peuvent être appliquées à une base de données comme celle-ci:
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
Masquage est la solution ad hoc au problème, mais ne fonctionne pas toujours bien en termes de vitesse et de mémoire.
avec indexation
en réglant l'index sur la colonne STK_ID
, nous pouvons utiliser l'objet de tranchage .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 le moyen rapide de le faire, même si l'indexation peut prendre un peu de temps, il permet de gagner du temps si vous voulez faire plusieurs requêtes de ce genre.
Fusion dataframes
cela peut aussi être fait en fusionnant des images de données. Cela correspondrait plus pour un scénario où 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 ya plusieurs lignes avec le même 'STK_ID'
vous pouvez utiliser query
, i.e.:
b = df.query('a > 1 & a < 5')
vous pouvez également obtenir des résultats similaires en utilisant "query" et@:
par exemple:
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']})
df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]})
list_of_values = [3,6]
result= df.query("A in @list_of_values")
result
A B
1 6 2
2 3 3