Como selecionar linhas de um DataFrame com base nos valores da coluna?

1961

Como selecionar linhas de um com DataFramebase em valores em alguma coluna no Python Pandas?

No SQL, eu usaria:

SELECT *
FROM table
WHERE colume_name = some_value

Tentei examinar a documentação dos pandas, mas não encontrei a resposta imediatamente.

szli
fonte
6
Esta é uma comparação com o SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html onde você pode executar os pandas como SQL.
I_thamary

Respostas:

3770

Para selecionar linhas cujo valor da coluna seja igual a um escalar some_value, use ==:

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

Para selecionar linhas cujo valor da coluna está em uma iterável some_values, use isin:

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

Combine várias condições com &:

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

Observe os parênteses. Devido às regras de precedência do operador do Python , &vincula mais firmemente que <=e >=. Assim, os parênteses no último exemplo são necessários. Sem parênteses

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

é analisado como

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

que resulta em um valor de verdade de uma série é um erro ambíguo .


Para selecionar linhas cujo valor da coluna não seja igual some_value , use !=:

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

isinretorna um booleano série, então para selecionar linhas cujo valor é não em some_values, negar a Série boolean usando ~:

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

Por exemplo,

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

rendimentos

     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 você tiver vários valores que deseja incluir, coloque-os em uma lista (ou, mais geralmente, em qualquer iterável) e use isin:

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

rendimentos

     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

Observe, no entanto, que se você deseja fazer isso várias vezes, é mais eficiente criar um índice primeiro e depois usar df.loc :

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

rendimentos

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

ou, para incluir vários valores do índice, use df.index.isin:

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

rendimentos

       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
fonte
19
De fato, df [df ['colume_name'] == some_value] também funciona. Mas minha primeira tentativa, df.where (df [ 'colume_name'] == some_value) não funciona ... não sei porquê ...
szli
13
Quando você usa df.where(condition), a condição deve ter a mesma forma que df.
unutbu
3
Esses links podem ser muito úteis para muitos de vocês: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas-dataframes
tremendows
8
FYI: Se você quiser selecionar uma linha baseada em dois (ou mais) etiquetas (tanto que requerem um ou ambos), consulte stackoverflow.com/questions/31756340/...
Shane
7
Desde df[df['column_name'] == some_value]obras, por que precisamos adicionar .locaqui?
Qqqwww
314

Existem várias maneiras de selecionar linhas de um quadro de dados do pandas:

  1. Indexação booleana ( df[df['col'] == value])
  2. Indexação posicional ( df.iloc[...])
  3. Indexação de etiquetas ( df.xs(...))
  4. df.query(...) API

Abaixo, mostro exemplos de cada um, com conselhos sobre quando usar determinadas técnicas. Suponha que nosso critério seja a coluna 'A'=='foo'

(Observação sobre desempenho: para cada tipo de base, podemos simplificar as coisas usando a API do pandas ou podemos nos aventurar fora da API, geralmente numpy, e acelerar as coisas.)


Configuração
A primeira coisa que precisamos é identificar uma condição que atuará como nosso critério para selecionar linhas. Começaremos com o caso do OP column_name == some_valuee incluiremos outros casos de uso comuns.

Empréstimos de @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. Indexação booleana

... A indexação booleana exige que o valor verdadeiro da 'A'coluna de cada linha seja igual a e 'foo', em seguida, use esses valores verdadeiros para identificar quais linhas manter. Normalmente, nomearíamos essa série, uma matriz de valores de verdade mask,. Faremos isso aqui também.

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

Podemos então usar essa máscara para cortar ou indexar o quadro de dados

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

Essa é uma das maneiras mais simples de realizar essa tarefa e, se o desempenho ou a intuição não forem um problema, esse deve ser o método escolhido. No entanto, se o desempenho for uma preocupação, convém considerar uma maneira alternativa de criar o mask.


2. Indexação posicional

A indexação posicional ( df.iloc[...]) tem seus casos de uso, mas este não é um deles. Para identificar onde dividir, primeiro precisamos executar a mesma análise booleana que fizemos acima. Isso nos deixa executando uma etapa extra para realizar a mesma tarefa.

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. Indexação de etiquetas

A indexação de etiquetas pode ser muito útil, mas, neste caso, estamos trabalhando novamente sem nenhum benefício

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é uma maneira muito elegante / intuitiva de executar essa tarefa, mas geralmente é mais lenta. No entanto , se você prestar atenção aos horários abaixo, para dados grandes, a consulta é muito eficiente. Mais do que a abordagem padrão e de magnitude semelhante à minha melhor sugestão.

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

Minha preferência é usar o Boolean mask

As melhorias reais podem ser feitas modificando a forma como criamos o nosso Boolean mask.

maskalternativa 1
Use a numpymatriz subjacente e renuncie à sobrecarga de criar outrapd.Series

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

Mostrarei testes de tempo mais completos no final, mas dê uma olhada nos ganhos de desempenho que obtemos usando o quadro de dados de amostra. Primeiro, analisamos a diferença na criação domask

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

Avaliar o maskcom a numpymatriz é ~ 30 vezes mais rápido. Isso se deve em parte à numpyavaliação frequentemente mais rápida. Também se deve em parte à falta de sobrecarga necessária para criar um índice e um pd.Seriesobjeto correspondente .

A seguir, veremos o momento para fatiar com um maskversus o outro.

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)

Os ganhos de desempenho não são tão pronunciados. Vamos ver se isso se sustenta em testes mais robustos.


maskalternativa 2
Poderíamos ter reconstruído o quadro de dados também. Há uma grande ressalva ao reconstruir um quadro de dados - você deve cuidar disso dtypesao fazer isso!

Em vez de df[mask]fazermos isso

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

Se o quadro de dados for do tipo misto, como é o nosso exemplo, quando obtermos df.valuesa matriz resultante for dtype objecte, consequentemente, todas as colunas do novo quadro de dados serão de dtype object. Exigindo, assim, astype(df.dtypes)e eliminando possíveis ganhos de desempenho.

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

No entanto, se o quadro de dados não for do tipo misto, essa é uma maneira muito útil de fazê-lo.

Dado

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)

Versus

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

Reduzimos o tempo pela metade.


maskalternativa 3 O
@unutbu também nos mostra como usar pd.Series.isinpara contabilizar cada elemento de df['A']estar em um conjunto de valores. Isso avalia o mesmo se nosso conjunto de valores é um conjunto de um valor, a saber 'foo'. Mas também generaliza para incluir conjuntos maiores de valores, se necessário. Acontece que isso ainda é muito rápido, mesmo que seja uma solução mais geral. A única perda real está na intuição para aqueles que não estão familiarizados com o conceito.

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

No entanto, como antes, podemos utilizar numpy para melhorar o desempenho sem sacrificar praticamente nada. Vamos usarnp.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

Cronometragem
Vou incluir outros conceitos mencionados em outras postagens e também para referência.
Código Abaixo

Cada coluna nesta tabela representa um quadro de dados de comprimento diferente, sobre o qual testamos cada função. Cada coluna mostra o tempo relativo gasto, com a função mais rápida com um índice 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

Você notará que os tempos mais rápidos parecem ser compartilhados entre mask_with_valuesemask_with_in1d

res.T.plot(loglog=True)

insira a descrição da imagem aqui

Funções

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]

Teste

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)

Momento especial
Analisando o caso especial em que temos um único não-objeto dtypepara todo o quadro de dados. Código Abaixo

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

Acontece que a reconstrução não vale a pena além de algumas centenas de linhas.

spec.T.plot(loglog=True)

insira a descrição da imagem aqui

Funções

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
)

Teste

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
fonte
6
Resposta fantástica! 2 perguntas, no entanto, i) como se .iloc(numpy.where(..))compara nesse esquema? ii) você esperaria que as classificações fossem as mesmas ao usar várias condições?
posdef
3
Para desempenho de pd.Series.isin, observe que ele é usado np.in1dem um cenário específico, usa khash em outros e aplica implicitamente uma compensação entre o custo do hash e o desempenho em situações específicas. Esta resposta tem mais detalhes.
jpp
1
Em 9 telas, isso é uma sobrecarga para um usuário novo ou mesmo intermediário. Você pode e deve auto-resumir o texto no primeiro parágrafo.
SMCI
@piRSquared Scaling importa Você se importaria, @piRSquared, para também colocar a sua experiência sobre quão bem os reais [{P|EXP}TIME] - e [{C|P|EXP}SPACE]- os custos de utilização do acima formas propostas de bloco-sintaxe (processamento de cima para baixo todo o dataframes de uma vez) crescer , nomeadamente quando dimensionado para algumas ~1E6, ~1E9, ~1E12contagens de linha? Obrigado por nos mostrar toda a imagem, senhor. As leituras quantitativas de benchmark com [min, Avg, MAX, StDev]são sempre bem-vindas, pois os valores mine MAXacompanham o Mean/StDevalívio do lote.
user3666197
Excelente resposta! A consulta resolveu meu problema!
Pavlos Ponos
281

tl; dr

Os pandas equivalentes a

select * from table where column_name = some_value

é

table[table.column_name == some_value]

Várias condições:

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

ou

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

Exemplo de código

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

No código acima, é a linha df[df.foo == 222]que fornece as linhas com base no valor da coluna,222 neste caso.

Várias condições também são possíveis:

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

Mas nesse ponto, eu recomendaria usar a função de consulta , pois é menos detalhada e produz o mesmo resultado:

df.query('foo == 222 | bar == 444')
imolit
fonte
5
queryé a única resposta aqui que é compatível com o encadeamento de métodos. Parece que são os pandas analógicos filterno dplyr.
Berk U.
3
Olá, no seu terceiro exemplo (várias colunas), acho que você precisa de colchetes, [não de colchetes (do lado de fora.
user2739472
2
no começo eu pensei que |era para AND, mas é claro que é operador de OR ... #
09 -0:
para várias condições usando AND, se pode fazerdf[condition1][condition2]
Ritwik
1
Deixando isso aqui para o caso de ser útil a alguém: a partir de 0,25 a consulta pode ser usada com nomes de colunas que possuem espaços no nome, colocando o nome nos backticks:df.query('`my col` == 124')
cs95
65

Acho que a sintaxe das respostas anteriores é redundante e difícil de lembrar. O Pandas introduziu o query()método na v0.13 e eu prefiro muito. Para sua pergunta, você poderia fazerdf.query('col == val')

Reproduzido 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

Você também pode acessar variáveis ​​no ambiente anexando um @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
fredcallaway
fonte
1
Você só precisa do pacote numexprinstalado.
MERose
4
No meu caso, eu precisava de cotação porque val é uma string. df.query ('col == "val"')
smerlung
28

Mais flexibilidade usando .querycom pandas >= 0.25.0:

Resposta atualizada de agosto de 2019

Como pandas >= 0.25.0podemos usar o querymétodo para filtrar quadros de dados com métodos pandas e até nomes de colunas que possuem espaços. Normalmente, os espaços nos nomes das colunas causariam um erro, mas agora podemos resolver isso usando um backtick (`), veja 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

Usando .querycom o método str.endswith:

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

Resultado

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

Também podemos usar variáveis ​​locais prefixando-a com um @em nossa consulta:

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

Resultado

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

Resultados mais rápidos podem ser obtidos usando numpy.where .

Por exemplo, com a configuração do 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

Comparações de tempo:

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
fonte
24

Aqui está um exemplo simples

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
fonte
17

Para selecionar apenas colunas específicas de várias colunas para um determinado valor em pandas:

select col_name1, col_name2 from table where column_name = some_value.

Opções:

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

ou

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

Para anexar a esta famosa questão (embora um pouco tarde demais): Você também pode df.groupby('column_name').get_group('column_desired_value').reset_index()fazer um novo quadro de dados com a coluna especificada com um valor específico. Por exemplo

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)

Execute isto 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
TuanDT
fonte
Ótima resposta. Gostaria apenas de acrescentar que o segundo (pd.DataFrame) é redundante porque get_group()retornará automaticamente um quadro de dados. Além disso, você pode apenas dizer "drop = True" como um parâmetro de reset_index(). Em outras palavras, pode ser reduzido para: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott
7

Você também pode usar .apply:

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

Na verdade, funciona em linha (isto é, aplica a função a cada linha).

A saída é

   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

Os resultados são os mesmos que os mencionados em @unutbu

df[[df['B'].isin(['one','three'])]]
Vahidn
fonte