Comment sélectionner des lignes dans un DataFrame en fonction des valeurs d'une colonne de Python Pandas?

En SQL, j'utiliserais:

SELECT *
FROM table
WHERE colume_name = some_value

J'ai essayé de regarder la documentation des pandas mais je n'ai pas trouvé immédiatement la réponse.

1791
szli 12 juin 2013 à 21:42

9 réponses

Meilleure réponse

Pour sélectionner des lignes dont la valeur de colonne est égale à un scalaire, some_value, utilisez ==:

df.loc[df['column_name'] == some_value]

Pour sélectionner des lignes dont la valeur de colonne est dans un itérable, some_values, utilisez isin:

df.loc[df['column_name'].isin(some_values)]

Combinez plusieurs conditions avec &:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]

Notez les parenthèses. En raison des règles de priorité des opérateurs de Python, & lie plus étroitement que <= et >=. Ainsi, les parenthèses dans le dernier exemple sont nécessaires. Sans les parenthèses

df['column_name'] >= A & df['column_name'] <= B

Est analysé comme

df['column_name'] >= (A & df['column_name']) <= B

Ce qui se traduit par un La valeur de vérité d'une série est une erreur ambiguë.


Pour sélectionner des lignes dont la valeur de colonne n'est pas égale some_value, utilisez !=:

df.loc[df['column_name'] != some_value]

isin renvoie une série booléenne, donc pour sélectionner des lignes dont la valeur n'est pas dans some_values, annulez la série booléenne en utilisant ~:

df.loc[~df['column_name'].isin(some_values)]

Par exemple,

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

Les rendements

     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Si vous souhaitez inclure plusieurs valeurs, placez-les dans un liste (ou plus généralement, tout itérable) et utilisez isin:

print(df.loc[df['B'].isin(['one','three'])])

Les rendements

     A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Notez cependant que si vous souhaitez effectuer cette opération plusieurs fois, il est plus efficace de faites d'abord un index, puis utilisez df.loc:

df = df.set_index(['B'])
print(df.loc['one'])

Les rendements

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

Ou, pour inclure plusieurs valeurs de l'index, utilisez df.index.isin:

df.loc[df.index.isin(['one','two'])]

Les rendements

       A  C   D
B              
one  foo  0   0
one  bar  1   2
two  foo  2   4
two  foo  4   8
two  bar  5  10
one  foo  6  12
3405
unutbu 18 janv. 2019 à 02:47

Voici un exemple simple

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111
21
DataByDavid 13 juin 2013 à 11:49

Plus de flexibilité en utilisant .query avec pandas >= 0.25.0:

Réponse mise à jour d'août 2019

Depuis pandas >= 0.25.0, nous pouvons utiliser la méthode query pour filtrer les trames de données avec des méthodes pandas et même des noms de colonnes qui ont des espaces. Normalement, les espaces dans les noms de colonnes donneraient une erreur, mais maintenant nous pouvons résoudre cela en utilisant un backtick (`) voir GitHub:

# Example dataframe
df = pd.DataFrame({'Sender email':['ex@example.com', "reply@shop.com", "buy@shop.com"]})

     Sender email
0  ex@example.com
1  reply@shop.com
2    buy@shop.com

Utilisation de .query avec la méthode str.endswith:

df.query('`Sender email`.str.endswith("@shop.com")')

Sortie

     Sender email
1  reply@shop.com
2    buy@shop.com

Nous pouvons également utiliser des variables locales en le préfixant avec un @ dans notre requête:

domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')

Sortie

     Sender email
1  reply@shop.com
2    buy@shop.com
18
Erfan 4 août 2019 à 12:59

Pour ajouter à cette fameuse question (mais un peu trop tard): Vous pouvez également faire df.groupby('column_name').get_group('column_desired_value').reset_index() pour créer un nouveau bloc de données avec une colonne spécifiée ayant une valeur particulière. Par exemple.

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)

Exécutez cela donne:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two
12
TuanDT 18 nov. 2016 à 12:10

Vous pouvez également utiliser .apply:

df.apply(lambda row: row[df['B'].isin(['one','three'])])

Il fonctionne en fait par ligne (c'est-à-dire qu'il applique la fonction à chaque ligne).

La sortie est

   A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

Les résultats sont les mêmes que ceux utilisés par @unutbu

df[[df['B'].isin(['one','three'])]]
5
Vahidn 7 déc. 2018 à 17:38

Tl; dr

Les pandas équivalents à

select * from table where column_name = some_value

Est

table[table.column_name == some_value]

Conditions multiples:

table[(table.column_name == some_value) | (table.column_name2 == some_value2)]

Ou

table.query('column_name == some_value | column_name2 == some_value2')

Exemple de code

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222], 
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo 
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

Dans le code ci-dessus, c'est la ligne df[df.foo == 222] qui donne les lignes en fonction de la valeur de la colonne, 222 dans ce cas.

Plusieurs conditions sont également possibles:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

Mais à ce stade, je recommanderais d'utiliser la requête fonction, car elle est moins verbeuse et donne le même résultat:

df.query('foo == 222 | bar == 444')
270
imolit 28 juin 2018 à 15:30

Pour sélectionner uniquement des colonnes spécifiques parmi plusieurs colonnes pour une valeur donnée dans pandas:

select col_name1, col_name2 from table where column_name = some_value.

Options:

df.loc[df['column_name'] == some_value][[col_name1, col_name2]]

Ou

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
15
firelynx 22 juin 2018 à 07:44

Des résultats plus rapides peuvent être obtenus en utilisant numpy.where.

Par exemple, avec configuration d'unubtu -

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

Comparaisons de synchronisation:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop
23
Brian Burns 3 oct. 2017 à 16:17

Je trouve la syntaxe des réponses précédentes redondante et difficile à retenir. Les pandas ont introduit la méthode query() dans la v0.13 et je la préfère de beaucoup. Pour votre question, vous pouvez faire df.query('col == val')

Reproduit de http://pandas.pydata.org/pandas-docs/ version / 0.17.0 / indexing.html # indexing-query

In [167]: n = 10

In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))

In [169]: df
Out[169]: 
          a         b         c
0  0.687704  0.582314  0.281645
1  0.250846  0.610021  0.420121
2  0.624328  0.401816  0.932146
3  0.011763  0.022921  0.244186
4  0.590198  0.325680  0.890392
5  0.598892  0.296424  0.007312
6  0.634625  0.803069  0.123872
7  0.924168  0.325076  0.303746
8  0.116822  0.364564  0.454607
9  0.986142  0.751953  0.561512

# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]: 
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

Vous pouvez également accéder aux variables dans l'environnement en ajoutant un @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
59
fredcallaway 9 févr. 2016 à 01:36