Comment implémenter 'in' et 'not in' pour un pandas DataFrame?
Pandas propose deux méthodes: Series.isin
et DataFrame.isin
pour Series et DataFrames, respectivement.
Filtrer le DataFrame basé sur UNE colonne (s'applique également à la série)
Le scénario le plus courant consiste à appliquer une isin
condition sur une colonne spécifique pour filtrer les lignes d'un DataFrame.
df = pd.DataFrame({'countries': ['US', 'UK', 'Germany', np.nan, 'China']})
df
countries
0 US
1 UK
2 Germany
3 China
c1 = ['UK', 'China'] # list
c2 = {'Germany'} # set
c3 = pd.Series(['China', 'US']) # Series
c4 = np.array(['US', 'UK']) # array
Series.isin
accepte différents types d'entrée. Voici tous les moyens valables d'obtenir ce que vous voulez:
df['countries'].isin(c1)
0 False
1 True
2 False
3 False
4 True
Name: countries, dtype: bool
# `in` operation
df[df['countries'].isin(c1)]
countries
1 UK
4 China
# `not in` operation
df[~df['countries'].isin(c1)]
countries
0 US
2 Germany
3 NaN
# Filter with `set` (tuples work too)
df[df['countries'].isin(c2)]
countries
2 Germany
# Filter with another Series
df[df['countries'].isin(c3)]
countries
0 US
4 China
# Filter with array
df[df['countries'].isin(c4)]
countries
0 US
1 UK
Filtrer sur BEAUCOUP de colonnes
Parfois, vous souhaiterez appliquer une vérification d'adhésion "in" avec certains termes de recherche sur plusieurs colonnes,
df2 = pd.DataFrame({
'A': ['x', 'y', 'z', 'q'], 'B': ['w', 'a', np.nan, 'x'], 'C': np.arange(4)})
df2
A B C
0 x w 0
1 y a 1
2 z NaN 2
3 q x 3
c1 = ['x', 'w', 'p']
Pour appliquer la isin
condition aux deux colonnes "A" et "B", utilisez DataFrame.isin
:
df2[['A', 'B']].isin(c1)
A B
0 True True
1 False False
2 False False
3 False True
De là, pour conserver les lignes où se trouve au moins une colonneTrue
, nous pouvons utiliser le any
long du premier axe:
df2[['A', 'B']].isin(c1).any(axis=1)
0 True
1 False
2 False
3 True
dtype: bool
df2[df2[['A', 'B']].isin(c1).any(axis=1)]
A B C
0 x w 0
3 q x 3
Notez que si vous souhaitez rechercher chaque colonne, vous omettez simplement l'étape de sélection de colonne et
df2.isin(c1).any(axis=1)
De même, pour conserver les lignes là où se trouvent TOUTES les colonnesTrue
, utilisez all
de la même manière que précédemment.
df2[df2[['A', 'B']].isin(c1).all(axis=1)]
A B C
0 x w 0
Notable Mentionne: numpy.isin
, query
, compréhensions liste (données de chaîne)
En plus des méthodes décrites ci - dessus, vous pouvez également utiliser l'équivalent numpy: numpy.isin
.
# `in` operation
df[np.isin(df['countries'], c1)]
countries
1 UK
4 China
# `not in` operation
df[np.isin(df['countries'], c1, invert=True)]
countries
0 US
2 Germany
3 NaN
Pourquoi vaut-il la peine d'envisager? Les fonctions NumPy sont généralement un peu plus rapides que leurs équivalents pandas en raison d'une surcharge réduite. Comme il s'agit d'une opération élément par élément qui ne dépend pas de l'alignement des index, il existe très peu de situations où cette méthode ne remplace pas convenablement les pandas.isin
.
Les routines Pandas sont généralement itératives lorsque vous travaillez avec des chaînes, car les opérations sur les chaînes sont difficiles à vectoriser. De nombreuses preuves suggèrent que la compréhension des listes sera plus rapide ici. . Nous avons recours à un in
chèque maintenant.
c1_set = set(c1) # Using `in` with `sets` is a constant time operation...
# This doesn't matter for pandas because the implementation differs.
# `in` operation
df[[x in c1_set for x in df['countries']]]
countries
1 UK
4 China
# `not in` operation
df[[x not in c1_set for x in df['countries']]]
countries
0 US
2 Germany
3 NaN
Cependant, il est beaucoup plus difficile à spécifier, alors ne l'utilisez pas à moins de savoir ce que vous faites.
Enfin, il y a aussi DataFrame.query
ce qui a été couvert dans cette réponse . numexpr FTW!