Come selezionare le righe da un DataFrame in base ai valori di colonna?


1963

Come selezionare le righe in DataFramebase ai valori di alcune colonne in Python Panda?

In SQL, vorrei usare:

SELECT *
FROM table
WHERE colume_name = some_value

Ho provato a guardare la documentazione di Panda ma non ho trovato immediatamente la risposta.



6
Questo è un confronto con SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html dove è possibile eseguire i panda come SQL.
i_thamary,

Risposte:


3772

Per selezionare le righe il cui valore di colonna è uguale a uno scalare some_value, utilizzare ==:

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

Per selezionare le righe il cui valore di colonna è in un iterabile some_values, utilizzare isin:

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

Combina più condizioni con &:

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

Nota le parentesi. A causa delle regole di precedenza dell'operatore di Python , si &lega più strettamente di <=e >=. Pertanto, le parentesi nell'ultimo esempio sono necessarie. Senza le parentesi

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

viene analizzato come

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

che si traduce in un valore di verità di una serie è un errore ambiguo .


Per selezionare le righe il cui valore di colonna non è uguale some_value , utilizzare !=:

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

isinrestituisce una serie booleana, quindi per selezionare le righe il cui valore non è in some_values, annulla la serie booleana usando ~:

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

Per esempio,

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

i rendimenti

     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

Se hai più valori che vuoi includere, inseriscili in un elenco (o più in generale, qualsiasi iterabile) e usa isin:

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

i rendimenti

     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

Si noti, tuttavia, che se si desidera farlo più volte, è più efficiente creare prima un indice e quindi utilizzarlo df.loc :

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

i rendimenti

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

oppure, per includere più valori dall'indice utilizzare df.index.isin:

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

i rendimenti

       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

19
In effetti, df [df ['nome_colume'] == valore_unico] funziona anche. Ma il mio primo tentativo, df.where (df ['colume_name'] == some_value) non funziona ... non so perché ...
szli

13
Quando si utilizza df.where(condition), la condizione deve avere la stessa forma di df.
unutbu,


8
Cordiali saluti: Se si desidera selezionare una riga in base a due (o più) etichette (che richiedono entrambi o entrambi), vedere stackoverflow.com/questions/31756340/…
Shane

7
Dal momento che df[df['column_name'] == some_value]funziona, perché dobbiamo aggiungere .locqui?
qqqwww,

314

Esistono diversi modi per selezionare le righe da un frame di dati Panda:

  1. Indicizzazione booleana ( df[df['col'] == value])
  2. Indicizzazione posizionale ( df.iloc[...])
  3. Indicizzazione etichetta ( df.xs(...))
  4. df.query(...) API

Di seguito vi mostro esempi di ciascuno, con consigli su quando utilizzare determinate tecniche. Supponiamo che il nostro criterio sia colonna'A' =='foo'

(Nota sulle prestazioni: per ogni tipo di base, possiamo mantenere le cose semplici usando l'API panda o possiamo avventurarci al di fuori dell'API, di solito numpy, e accelerare le cose.)


Installazione
La prima cosa di cui abbiamo bisogno è identificare una condizione che fungerà da nostro criterio per la selezione delle righe. Inizieremo con il caso del POcolumn_name == some_value e includeremo alcuni altri casi d'uso comuni.

Prendendo in prestito da @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. Indicizzazione booleana

... L'indicizzazione booleana richiede che il valore reale della 'A'colonna di ogni riga sia uguale 'foo', quindi utilizzare quei valori di verità per identificare quali righe mantenere. In genere, avremmo chiamiamo questa serie, una serie di valori di verità, mask. Lo faremo anche qui.

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

Possiamo quindi utilizzare questa maschera per suddividere o indicizzare il frame di dati

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

Questo è uno dei modi più semplici per eseguire questa attività e se le prestazioni o l'intuitività non sono un problema, questo dovrebbe essere il metodo scelto. Tuttavia, se le prestazioni sono un problema, allora potresti prendere in considerazione un modo alternativo di creare il file mask.


2. Indicizzazione posizionale

L'indicizzazione posizionale ( df.iloc[...]) ha i suoi casi d'uso, ma questo non è uno di questi. Per identificare dove tagliare, dobbiamo prima eseguire la stessa analisi booleana che abbiamo fatto sopra. Questo ci lascia fare un ulteriore passo per compiere lo stesso compito.

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. Indicizzazione dell'etichetta

L' indicizzazione delle etichette può essere molto utile, ma in questo caso stiamo di nuovo facendo più lavoro senza alcun vantaggio

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.queryè un modo molto elegante / intuitivo per eseguire questo compito, ma spesso è più lento. Tuttavia , se si presta attenzione ai tempi seguenti, per dati di grandi dimensioni, la query è molto efficiente. Più che un approccio standard e di grandezza simile al mio miglior suggerimento.

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

La mia preferenza è usare il Boolean mask

È possibile apportare miglioramenti effettivi modificando il modo in cui creiamo il nostro Boolean mask.

maskalternativa 1
Utilizzare l' numpyarray sottostante e rinunciare al sovraccarico di crearne un altropd.Series

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

Mostrerò alla fine test più completi sul tempo, ma diamo solo un'occhiata ai miglioramenti delle prestazioni che otteniamo usando il frame di dati di esempio. Innanzitutto, osserviamo la differenza nella creazione dimask

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

La valutazione maskcon l' numpyarray è ~ 30 volte più veloce. Ciò è in parte dovuto alla numpyvalutazione spesso più rapida. In parte è anche dovuto alla mancanza di costi generali necessari per costruire un indice e un corrispondentepd.Series oggetto .

Successivamente, esamineremo i tempi per tagliare con l'uno maskrispetto all'altro.

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)

I miglioramenti delle prestazioni non sono così pronunciati. Vedremo se questo regge su test più solidi.


maskalternativa 2
Avremmo potuto ricostruire anche il frame di dati. C'è un grande avvertimento quando si ricostruisce un dataframe: bisogna fare attenzione a dtypesfarlo!

Invece di df[mask]faremo questo

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

Se il frame di dati è di tipo misto, come nel nostro esempio, quando otteniamo df.valuesl'array risultante è dtype objecte di conseguenza, tutte le colonne del nuovo frame di dati saranno di dtype object. Richiedendo quindi astype(df.dtypes)e uccidendo qualsiasi potenziale miglioramento delle prestazioni.

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

Tuttavia, se il frame di dati non è di tipo misto, questo è un modo molto utile per farlo.

Dato

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)

Contro

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

Dividiamo il tempo a metà.


maskl'alternativa 3
@unutbu ci mostra anche come utilizzare pd.Series.isinper tenere conto di ogni elemento df['A']dell'essere in un insieme di valori. Ciò valuta la stessa cosa se il nostro insieme di valori è un insieme di un valore, vale a dire 'foo'. Ma si generalizza anche per includere set di valori più grandi, se necessario. Risulta, questo è ancora abbastanza veloce anche se è una soluzione più generale. L'unica vera perdita è nell'intuitività per coloro che non hanno familiarità con il concetto.

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

Tuttavia, come prima, possiamo utilizzare numpyper migliorare le prestazioni sacrificando praticamente nulla. Useremonp.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

Calendario
Includerò anche altri concetti citati in altri post come riferimento.
Codice sotto

Ogni colonna in questa tabella rappresenta un frame di dati di lunghezza diversa su cui testiamo ciascuna funzione. Ogni colonna mostra il tempo relativo impiegato, con la funzione più veloce dato un indice di base di 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

Noterai che i tempi più veloci sembrano essere condivisi tra mask_with_valuesemask_with_in1d

res.T.plot(loglog=True)

inserisci qui la descrizione dell'immagine

funzioni

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]

analisi

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)

Tempi speciali
Osservando il caso speciale quando abbiamo un singolo non oggetto dtypeper l'intero frame di dati. Codice sotto

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

Si scopre che la ricostruzione non vale la pena oltre alcune centinaia di file.

spec.T.plot(loglog=True)

inserisci qui la descrizione dell'immagine

funzioni

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
)

analisi

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)

6
Risposta fantastica! 2 domande però, i) come si .iloc(numpy.where(..))confronta in questo schema? ii) ti aspetti che le classifiche siano le stesse quando utilizzi più condizioni?
posdef

3
Per le prestazioni di pd.Series.isin, nota si fa uso np.in1dsotto il cofano in uno scenario specifico, usi Khash in altri, e si applica implicitamente un trade-off tra costi di hashing rispetto prestazioni in situazioni specifiche. Questa risposta ha più dettagli.
jpp,

1
A 9 schermate, questo è un modo per sovraccaricare un utente nuovo o addirittura intermedio. Puoi e dovresti riassumere da solo il tl; dr nel primo paragrafo.
smci,

@piRSquared Scaling conta ti dispiacerebbe, @piRSquared, di inviare anche la tua esperienza su quanto bene l'attuale [{P|EXP}TIME] - e [{C|P|EXP}SPACE]- i costi di utilizzo di quanto sopra proposto forme di blocchi di sintassi (elaborazione dall'alto verso il basso l'intero dataframes in una sola volta) crescere , vale a dire quando ridimensionato per alcuni ~1E6, ~1E9, ~1E12conteggi di righe? Grazie per averci mostrato il quadro completo, signore. Letture di riferimento quantitativa [min, Avg, MAX, StDev]sono sempre i benvenuti, in quanto sia l' mine MAXvalori accompagnano il Mean/StDevsollievo del lotto.
user3666197

Risposta eccellente! La query ha risolto il mio problema!
Pavlos Ponos,

281

tl; dr

I panda equivalgono a

select * from table where column_name = some_value

è

table[table.column_name == some_value]

Condizioni multiple:

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

o

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

Esempio di codice

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

Nel codice sopra è la riga df[df.foo == 222]che fornisce le righe in base al valore della colonna,222 in questo caso.

Sono anche possibili più condizioni:

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

Ma a quel punto consiglierei di utilizzare la funzione query , poiché è meno dettagliata e produce lo stesso risultato:

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

5
queryè l'unica risposta qui compatibile con il concatenamento di metodi. Sembra che sia l'analogo dei panda a filterin dplyr.
Berk U.

3
Ciao, nel tuo terzo esempio (più colonne) penso che tu abbia bisogno di parentesi quadre [non rotonde (all'esterno.
user2739472,

2
all'inizio pensavo che |fosse per AND, ma ovviamente è un operatore OR ...
O-9,

per più condizioni usando AND, si può faredf[condition1][condition2]
Ritwik

1
Lasciare questo qui nel caso in cui sia utile a qualcuno: da 0,25 la query può essere utilizzata con nomi di colonne che hanno spazi nel nome racchiudendo il nome in backtick:df.query('`my col` == 124')
cs95

65

Trovo che la sintassi delle risposte precedenti sia ridondante e difficile da ricordare. Panda ha introdotto il query()metodo in v0.13 e lo preferisco di gran lunga. Per la tua domanda, potresti farlodf.query('col == val')

Riprodotto da 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

È inoltre possibile accedere alle variabili nell'ambiente anteponendo un @.

exclude = ('red', 'orange')
df.query('color not in @exclude')

1
Hai solo bisogno del pacchetto numexprinstallato.
MERose,

4
Nel mio caso avevo bisogno di un preventivo perché val è una stringa. df.query ('col == "val"')
smerlung

28

Maggiore flessibilità grazie .querya pandas >= 0.25.0:

Risposta aggiornata di agosto 2019

Dal momento pandas >= 0.25.0che possiamo usare il querymetodo per filtrare i frame di dati con i metodi panda e persino i nomi delle colonne che hanno spazi. Normalmente gli spazi nei nomi delle colonne darebbero un errore, ma ora possiamo risolverlo usando un backtick (`) vedi 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

Usando .querycon il metodo str.endswith:

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

Produzione

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

Inoltre possiamo usare le variabili locali prefissandole con un @nella nostra query:

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

Produzione

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

26

Risultati più rapidi possono essere raggiunti usando numpy.where .

Ad esempio, con l'installazione di 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

Confronti temporali:

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

24

Qui c'è un semplice esempio

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

17

Per selezionare solo colonne specifiche da più colonne per un dato valore in panda:

select col_name1, col_name2 from table where column_name = some_value.

Opzioni:

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

o

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

16

Per aggiungere a questa famosa domanda (anche se un po 'troppo tardi): puoi anche fare df.groupby('column_name').get_group('column_desired_value').reset_index()un nuovo frame di dati con una colonna specificata con un valore particolare. Per esempio

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)

Esegui questo dà:

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

Bella risposta. Vorrei solo aggiungere che il secondo (pd.DataFrame) è ridondante perché get_group()restituirà automaticamente un frame di dati. Inoltre puoi semplicemente dire "drop = True" come parametro di reset_index(). In altre parole, può essere abbreviato in: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott

7

Puoi anche usare .apply:

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

In realtà funziona a livello di riga (vale a dire, applica la funzione a ciascuna riga).

L'output è

   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

I risultati sono gli stessi dell'utilizzo menzionato da @unutbu

df[[df['B'].isin(['one','three'])]]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.