[Python] Sélectionnez les lignes d'un DataFrame en fonction des valeurs d'une colonne dans pandas


Answers

tl; dr

Les pandas équivalents à

select * from table where column_name = some_value

est

table[table.column_name == some_value]

Plusieurs conditions:

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 basées sur 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 recommande d'utiliser la fonction de query , car elle est moins verbeuse et donne le même résultat:

df.query('foo == 222 | bar == 444')
Question

Comment sélectionner des lignes d'un DataFrame basé sur des valeurs dans une colonne de pandas?
En SQL j'utiliserais:

select * from table where colume_name = some_value. 

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




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})
df[df['A']=='foo']

OUTPUT:
   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



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

Par exemple, avec la 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 temps:

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



Je trouve la syntaxe des réponses précédentes redondante et difficile à retenir. Pandas a introduit la méthode query() dans 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')



Pour ajouter à cette fameuse question (bien qu'un peu trop tard): Vous pouvez aussi faire df.groupby('column_name').get_group('column_desired_value').reset_index() pour créer une nouvelle trame 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 ceci 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