J'ai un Python pandas _ DataFrame 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'ID de stock 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 rassembler toutes les lignes de certaines actions, telles 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 la cible?
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 sous-chaînes à rechercher, vous pouvez filtrer à l'aide de la méthode str.contains
et expressions régulières.
Par exemple, si nous souhaitons renvoyer un DataFrame contenant tous les ID de stock commençant par _'600'
_ et suivis de 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 ayons une liste de chaînes avec lesquelles nous voulons que les valeurs dans _'STK_ID'
_ se terminent, par ex.
_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 le DataFrame:
_>>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)]
... STK_ID ...
... '155905' ...
... '633101' ...
... '210302' ...
... ... ...
_
Enfin, contains
peut ignorer la casse (en définissant _case=False
_), ce qui vous permet d’être plus général lorsque vous spécifiez les chaînes que vous souhaitez faire correspondre.
Par exemple,
_str.contains('pandas', case=False)
_
correspondrait à PANDAS
, PanDAs
, _paNdAs123
_, etc.
vous pouvez également utiliser des plages en utilisant:
b = df[(df['a'] > 1) & (df['a'] < 5)]
Vous pouvez également directement requête votre DataFrame pour cette information.
rpt.query('STK_ID in (600809,600141,600329)')
Ou de même rechercher des gammes:
rpt.query('60000 < STK_ID < 70000')
Étant donné un dataframe comme ceci:
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.
La plus évidente est la fonction .isin
. Vous pouvez créer un masque qui vous donne une série d'instructions 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 ne fonctionne pas toujours bien en termes de vitesse et de mémoire.
En définissant l'index sur la colonne STK_ID
, nous pouvons utiliser l'objet de découpage pandas intégré .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, cela vous fait gagner du temps si vous souhaitez effectuer plusieurs requêtes de ce type.
Cela peut également être fait en fusionnant des images. Cela conviendrait mieux pour 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
Toutes les méthodes ci-dessus fonctionnent même s'il y a plusieurs lignes avec le même 'STK_ID'
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
Vous pouvez utiliser query
, à savoir:
b = df.query('a > 1 & a < 5')