Comment sélectionner des lignes dans un DataFrame en fonction des valeurs de colonne?

1964

Comment sélectionner des lignes à partir d'un DataFramebasé sur les valeurs d'une colonne dans 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 immédiatement trouvé la réponse.

Szli
la source
6
Il s'agit d'une comparaison avec SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html où vous pouvez exécuter des pandas en tant que SQL.
i_thamary

Réponses:

3775

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 , les &liaisons sont plus étroites 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

qui se traduit par une 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]

isinrenvoie 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 avez plusieurs valeurs que vous souhaitez inclure, mettez-les dans une liste (ou plus généralement, toute 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 créer d'abord un index, puis d'utiliser 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
unutbu
la source
19
En fait, df [df ['colume_name'] == some_value] fonctionne également. Mais ma première tentative, df.where (df ['colume_name'] == some_value) ne fonctionne pas ...
je
13
Lorsque vous utilisez df.where(condition), la condition doit avoir la même forme que df.
unutbu
3
Ces liens pourraient être très utiles pour beaucoup d'entre vous: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas-dataframes
tremendows
8
Pour info: si vous souhaitez sélectionner une ligne basée sur deux (ou plus) étiquettes (nécessitant les deux ou les deux), voir stackoverflow.com/questions/31756340/…
Shane
7
Depuis les df[df['column_name'] == some_value]travaux, pourquoi avons-nous besoin d'ajouter .locici?
qqqwww
314

Il existe plusieurs façons de sélectionner des lignes dans un bloc de données pandas:

  1. Indexation booléenne ( df[df['col'] == value])
  2. Indexation positionnelle ( df.iloc[...])
  3. Indexation des étiquettes ( df.xs(...))
  4. df.query(...) API

Ci-dessous, je vous montre des exemples de chacun, avec des conseils sur l'utilisation de certaines techniques. Supposons que notre critère est la colonne 'A'=='foo'

(Remarque sur les performances: pour chaque type de base, nous pouvons simplifier les choses en utilisant l'API pandas ou nous pouvons nous aventurer en dehors de l'API, généralement dans numpy, et accélérer les choses.)


Configuration
La première chose dont nous aurons besoin est d'identifier une condition qui servira de critère de sélection des lignes. Nous allons commencer par le cas de l'OP column_name == some_value, et inclure quelques autres cas d'utilisation courants.

Emprunter à @unutbu:

import pandas as pd, 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})

1. Indexation booléenne

... L'indexation booléenne nécessite de trouver la vraie valeur de la 'A'colonne de chaque ligne égale à 'foo', puis d'utiliser ces valeurs de vérité pour identifier les lignes à conserver. En règle générale, nous nommeriez cette série, un tableau de valeurs de vérité, mask. Nous le ferons ici aussi.

mask = df['A'] == 'foo'

Nous pouvons ensuite utiliser ce masque pour découper ou indexer la trame de données

df[mask]

     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

C'est l'un des moyens les plus simples d'accomplir cette tâche et si les performances ou l'intuitivité ne sont pas un problème, cela devrait être la méthode que vous avez choisie. Cependant, si les performances sont un problème, vous souhaiterez peut-être envisager une autre façon de créer le fichier mask.


2. Indexation positionnelle

L'indexation positionnelle ( df.iloc[...]) a ses cas d'utilisation, mais ce n'est pas l'un d'entre eux. Afin d'identifier où couper, nous devons d'abord effectuer la même analyse booléenne que nous avons faite ci-dessus. Cela nous laisse effectuer une étape supplémentaire pour accomplir la même tâche.

mask = df['A'] == 'foo'
pos = np.flatnonzero(mask)
df.iloc[pos]

     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

3. Indexation des étiquettes

L' indexation des étiquettes peut être très pratique, mais dans ce cas, nous faisons encore plus de travail sans aucun avantage

df.set_index('A', append=True, drop=False).xs('foo', level=1)

     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

4. df.query()API

pd.DataFrame.queryest un moyen très élégant / intuitif d'effectuer cette tâche, mais est souvent plus lent. Cependant , si vous faites attention aux délais ci-dessous, pour les données volumineuses, la requête est très efficace. Plus que l'approche standard et d'une ampleur similaire à ma meilleure suggestion.

df.query('A == "foo"')

     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

Ma préférence est d’utiliser le Boolean mask

De réelles améliorations peuvent être apportées en modifiant la façon dont nous créons notre Boolean mask.

maskalternative 1
Utilisez le numpytableau sous-jacent et renoncez à la surcharge de création d'un autrepd.Series

mask = df['A'].values == 'foo'

Je montrerai des tests de temps plus complets à la fin, mais jetez un coup d'œil aux gains de performances que nous obtenons en utilisant l'exemple de trame de données. Tout d'abord, nous examinons la différence dans la création dumask

%timeit mask = df['A'].values == 'foo'
%timeit mask = df['A'] == 'foo'

5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

L'évaluation maskavec le numpytableau est environ 30 fois plus rapide. Cela est dû en partie au fait que l' numpyévaluation est souvent plus rapide. Cela est également dû en partie au manque de surcharge nécessaire pour construire un index et un pd.Seriesobjet correspondant .

Ensuite, nous examinerons le moment du découpage avec l'un maskpar rapport à l'autre.

mask = df['A'].values == 'foo'
%timeit df[mask]
mask = df['A'] == 'foo'
%timeit df[mask]

219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Les gains de performances ne sont pas aussi prononcés. Nous verrons si cela résiste à des tests plus robustes.


maskalternative 2
Nous aurions pu également reconstruire la base de données. Il y a une grande mise en garde lors de la reconstruction d'une trame de données - vous devez en prendre soin dtypeslorsque vous le faites!

Au lieu de cela, df[mask]nous le ferons

pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

Si la trame de données est de type mixte, ce que notre exemple est, alors lorsque nous obtenons df.valuesle tableau résultant est de dtype objectet par conséquent, toutes les colonnes de la nouvelle trame de données seront de dtype object. Exigeant ainsi le astype(df.dtypes)et tuant tous les gains de performance potentiels.

%timeit df[m]
%timeit pd.DataFrame(df.values[mask], df.index[mask], df.columns).astype(df.dtypes)

216 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
1.43 ms ± 39.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Cependant, si le bloc de données n'est pas de type mixte, c'est un moyen très utile de le faire.

Donné

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

d1

   A  B  C  D  E
0  0  2  7  3  8
1  7  0  6  8  6
2  0  2  0  4  9
3  7  3  2  4  3
4  3  6  7  7  4
5  5  3  7  5  9
6  8  7  6  4  7
7  6  2  6  6  5
8  2  8  7  5  8
9  4  7  6  1  5    

%%timeit
mask = d1['A'].values == 7
d1[mask]

179 µs ± 8.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Contre

%%timeit
mask = d1['A'].values == 7
pd.DataFrame(d1.values[mask], d1.index[mask], d1.columns)

87 µs ± 5.12 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Nous avons réduit le temps de moitié.


maskl'alternative 3
@unutbu nous montre également comment utiliser pd.Series.isinpour tenir compte de chaque élément d' df['A']être dans un ensemble de valeurs. Cela équivaut à la même chose si notre ensemble de valeurs est un ensemble d'une valeur, à savoir 'foo'. Mais il se généralise également pour inclure des ensembles de valeurs plus importants si nécessaire. Il s'avère que c'est encore assez rapide même s'il s'agit d'une solution plus générale. La seule vraie perte est dans l'intuitivité pour ceux qui ne connaissent pas le concept.

mask = df['A'].isin(['foo'])
df[mask]

     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

Cependant, comme auparavant, nous pouvons utiliser numpypour améliorer les performances tout en ne sacrifiant pratiquement rien. Nous utiliseronsnp.in1d

mask = np.in1d(df['A'].values, ['foo'])
df[mask]

     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

Calendrier
Je vais également inclure d'autres concepts mentionnés dans d'autres articles pour référence.
Code ci-dessous

Chaque colonne de ce tableau représente une trame de données de longueur différente sur laquelle nous testons chaque fonction. Chaque colonne montre le temps relatif pris, avec la fonction la plus rapide étant donné un indice de base de 1.0.

res.div(res.min())

                         10        30        100       300       1000      3000      10000     30000
mask_standard         2.156872  1.850663  2.034149  2.166312  2.164541  3.090372  2.981326  3.131151
mask_standard_loc     1.879035  1.782366  1.988823  2.338112  2.361391  3.036131  2.998112  2.990103
mask_with_values      1.010166  1.000000  1.005113  1.026363  1.028698  1.293741  1.007824  1.016919
mask_with_values_loc  1.196843  1.300228  1.000000  1.000000  1.038989  1.219233  1.037020  1.000000
query                 4.997304  4.765554  5.934096  4.500559  2.997924  2.397013  1.680447  1.398190
xs_label              4.124597  4.272363  5.596152  4.295331  4.676591  5.710680  6.032809  8.950255
mask_with_isin        1.674055  1.679935  1.847972  1.724183  1.345111  1.405231  1.253554  1.264760
mask_with_in1d        1.000000  1.083807  1.220493  1.101929  1.000000  1.000000  1.000000  1.144175

Vous remarquerez que les temps les plus rapides semblent être partagés entre mask_with_valuesetmask_with_in1d

res.T.plot(loglog=True)

entrez la description de l'image ici

Les fonctions

def mask_standard(df):
    mask = df['A'] == 'foo'
    return df[mask]

def mask_standard_loc(df):
    mask = df['A'] == 'foo'
    return df.loc[mask]

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_values_loc(df):
    mask = df['A'].values == 'foo'
    return df.loc[mask]

def query(df):
    return df.query('A == "foo"')

def xs_label(df):
    return df.set_index('A', append=True, drop=False).xs('foo', level=-1)

def mask_with_isin(df):
    mask = df['A'].isin(['foo'])
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

Essai

res = pd.DataFrame(
    index=[
        'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
        'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
    ],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

for j in res.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in res.index:a
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        res.at[i, j] = timeit(stmt, setp, number=50)

Timing spécial
En regardant le cas spécial où nous avons un seul non-objet dtypepour la trame de données entière. Code ci-dessous

spec.div(spec.min())

                     10        30        100       300       1000      3000      10000     30000
mask_with_values  1.009030  1.000000  1.194276  1.000000  1.236892  1.095343  1.000000  1.000000
mask_with_in1d    1.104638  1.094524  1.156930  1.072094  1.000000  1.000000  1.040043  1.027100
reconstruct       1.000000  1.142838  1.000000  1.355440  1.650270  2.222181  2.294913  3.406735

Il s'avère que la reconstruction n'en vaut pas la peine après quelques centaines de rangées.

spec.T.plot(loglog=True)

entrez la description de l'image ici

Les fonctions

np.random.seed([3,1415])
d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))

def mask_with_values(df):
    mask = df['A'].values == 'foo'
    return df[mask]

def mask_with_in1d(df):
    mask = np.in1d(df['A'].values, ['foo'])
    return df[mask]

def reconstruct(df):
    v = df.values
    mask = np.in1d(df['A'].values, ['foo'])
    return pd.DataFrame(v[mask], df.index[mask], df.columns)

spec = pd.DataFrame(
    index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
    columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    dtype=float
)

Essai

for j in spec.columns:
    d = pd.concat([df] * j, ignore_index=True)
    for i in spec.index:
        stmt = '{}(d)'.format(i)
        setp = 'from __main__ import d, {}'.format(i)
        spec.at[i, j] = timeit(stmt, setp, number=50)
piRSquared
la source
6
Une réponse fantastique! 2 questions cependant, i) comment .iloc(numpy.where(..))comparer dans ce schéma? ii) vous attendriez-vous à ce que les classements soient les mêmes lorsque vous utilisez plusieurs conditions?
posdef
3
Pour l' exécution de pd.Series.isin, notez qu'il fait usage np.in1dsous le capot dans un scénario spécifique, les utilisations khash dans d' autres, et applique implicitement un compromis entre le coût de hachage par rapport à la performance dans des situations spécifiques. Cette réponse a plus de détails.
jpp
1
À 9 écrans, c'est une surcharge de manière pour un utilisateur nouveau ou même intermédiaire. Vous pouvez et devez résumer vous-même le tl; dr dans le premier paragraphe.
smci
@piRSquared Mise à l' échelle des questions Pourriez - vous, @piRSquared, pour poster aussi votre expérience à quel point les réels [{P|EXP}TIME] - et [{C|P|EXP}SPACE]- les coûts d'utilisation de ce qui précède les formes proposées de bloc-syntaxe (traitement de haut en bas l'ensemble dataframes à la fois) se développer , à savoir quand mis à l'échelle pour certains nombres de ~1E6, ~1E9, ~1E12lignes? Merci de nous avoir montré toute l'image, monsieur. Les lectures de référence quantitatives avec [min, Avg, MAX, StDev]sont toujours les bienvenues, car les valeurs minet MAXaccompagnent le Mean/StDevsoulagement du lot.
user3666197
Excellente réponse! La requête a résolu mon problème!
Pavlos Ponos
281

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, 222dans 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 fonction de requête , car elle est moins détaillée et donne le même résultat:

df.query('foo == 222 | bar == 444')
imolit
la source
5
queryest la seule réponse ici compatible avec le chaînage de méthodes. Il semble que ce soit l'analogue des pandas filterdans dplyr.
Berk U.
3
Bonjour, dans votre troisième exemple (plusieurs colonnes), je pense que vous avez besoin de crochets et [non de crochets (à l'extérieur.
user2739472
2
au début, je pensais que |c'était pour ET, mais bien sûr, c'est l'opérateur OR ...
O-9
pour plusieurs conditions en utilisant AND, on peut le fairedf[condition1][condition2]
Ritwik
1
Laissant cela ici juste au cas où cela serait utile à quelqu'un: à partir de 0,25, la requête peut être utilisée avec des noms de colonne qui ont des espaces dans le nom en insérant le nom entre guillemets:df.query('`my col` == 124')
cs95
65

Je trouve la syntaxe des réponses précédentes redondante et difficile à retenir. Les pandas ont introduit la query()méthode en v0.13 et je la préfère de beaucoup. Pour votre question, vous pourriez fairedf.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')
fredcallaway
la source
1
Vous n'avez besoin que d'un package numexprinstallé.
MERose
4
Dans mon cas, j'avais besoin de devis parce que val est une chaîne. df.query ('col == "val"')
smerlung
28

Plus de flexibilité .queryavec pandas >= 0.25.0:

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

Puisque pandas >= 0.25.0nous pouvons utiliser la queryméthode 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':['[email protected]', "[email protected]", "[email protected]"]})

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

Utilisation .queryavec méthode str.endswith:

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

Production

     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)')

Production

     Sender email
1  reply@shop.com
2    buy@shop.com
Erfan
la source
26

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 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
shivsn
la source
24

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
DataByDavid
la source
17

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]]
SP001
la source
16

Pour ajouter à cette fameuse question (bien qu'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
TuanDT
la source
Très bonne réponse. Je voudrais juste ajouter que le second (pd.DataFrame) est redondant car get_group()retournera automatiquement une trame de données. Vous pouvez également dire "drop = True" comme paramètre de reset_index(). En d'autres termes, il peut être raccourci comme suit: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott
7

Vous pouvez également utiliser .apply:

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

Il fonctionne en fait ligne 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'])]]
Vahidn
la source