¿Cómo seleccionar filas de un DataFrame basado en valores de columna?

1963

¿Cómo seleccionar filas de una DataFramebase en valores en alguna columna en Python Pandas?

En SQL, usaría:

SELECT *
FROM table
WHERE colume_name = some_value

Traté de mirar la documentación de los pandas pero no encontré la respuesta de inmediato.

szli
fuente
66
Esta es una comparación con SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html donde puede ejecutar pandas como SQL.
i_thamary

Respuestas:

3773

Para seleccionar filas cuyo valor de columna sea igual a un escalar some_value, use ==:

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

Para seleccionar filas cuyo valor de columna esté en un iterable some_values, use isin:

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

Combina múltiples condiciones con &:

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

Tenga en cuenta los paréntesis. Debido a las reglas de precedencia del operador de Python , se &une con más fuerza que <=y >=. Por lo tanto, los paréntesis en el último ejemplo son necesarios. Sin los paréntesis

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

se analiza como

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

lo que resulta en un valor de verdad de una serie es un error ambiguo .


Para seleccionar filas cuyo valor de columna no sea igual some_value , use !=:

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

isindevuelve una serie booleana, por lo que para seleccionar filas cuyo valor no está en some_values, niegue la serie booleana usando ~:

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

Por ejemplo,

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

rendimientos

     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 tiene varios valores que desea incluir, colóquelos en una lista (o más generalmente, cualquier iterable) y use isin:

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

rendimientos

     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

Sin embargo, tenga en cuenta que si desea hacer esto muchas veces, es más eficiente hacer un índice primero y luego usar df.loc:

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

rendimientos

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

o, para incluir múltiples valores del uso del índice df.index.isin:

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

rendimientos

       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
fuente
19
De hecho, df [df ['colume_name'] == some_value] también funciona. Pero mi primer intento, df.where (df ['colume_name'] == some_value) no funciona ... no estoy seguro de por qué ...
szli
13
Cuando lo usa df.where(condition), la condición tiene que tener la misma forma que df.
unutbu
3
Esos enlaces podrían ser muy útiles para muchos de ustedes: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas-dataframes
tremendows
8
FYI: Si desea seleccionar una fila basada en dos (o más) etiquetas (ya sea que requieran ambas o cualquiera), consulte stackoverflow.com/questions/31756340/…
Shane
77
Ya que df[df['column_name'] == some_value]funciona, ¿por qué necesitamos agregar .locaquí?
qqqwww
314

Hay varias formas de seleccionar filas de un marco de datos de pandas:

  1. Indización booleana ( df[df['col'] == value])
  2. Indexación posicional ( df.iloc[...])
  3. Indización de etiquetas ( df.xs(...))
  4. df.query(...) API

A continuación les muestro ejemplos de cada uno, con consejos sobre cuándo usar ciertas técnicas. Supongamos que nuestro criterio es la columna 'A'=='foo'

(Nota sobre el rendimiento: para cada tipo de base, podemos simplificar las cosas mediante el uso de la API de pandas o podemos aventurarnos fuera de la API, por lo general numpy, y acelerar las cosas).


Configuración
Lo primero que necesitaremos es identificar una condición que actuará como nuestro criterio para seleccionar filas. Comenzaremos con el caso del OP column_name == some_valuee incluiremos algunos otros casos de uso comunes.

Préstamo 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. indexación booleana

... la indexación booleana requiere encontrar el valor verdadero de la 'A'columna de cada fila que sea igual 'foo', y luego usar esos valores de verdad para identificar qué filas mantener. Por lo general, nos nombramos esta serie, una serie de valores de verdad, mask. Lo haremos aquí también.

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

Entonces podemos usar esta máscara para cortar o indexar el marco de datos

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

Esta es una de las formas más simples de realizar esta tarea y si el rendimiento o la intuición no son un problema, este debería ser el método elegido. Sin embargo, si el rendimiento es una preocupación, es posible que desee considerar una forma alternativa de crear el mask.


2. indexación posicional

La indexación posicional ( df.iloc[...]) tiene sus casos de uso, pero este no es uno de ellos. Para identificar dónde dividir, primero debemos realizar el mismo análisis booleano que hicimos anteriormente. Esto nos deja realizando un paso adicional para lograr la misma tarea.

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. Indización de etiquetas

La indexación de etiquetas puede ser muy útil, pero en este caso, nuevamente estamos haciendo más trabajo sin beneficio

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.queryes una forma muy elegante / intuitiva de realizar esta tarea, pero a menudo es más lenta. Sin embargo , si presta atención a los tiempos a continuación, para datos grandes, la consulta es muy eficiente. Más que el enfoque estándar y de magnitud similar a mi mejor sugerencia.

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

Mi preferencia es usar el Boolean mask

Se pueden hacer mejoras reales modificando cómo creamos nuestro Boolean mask.

maskalternativa 1
Use la numpymatriz subyacente y renuncie a la sobrecarga de crear otrapd.Series

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

Mostraré pruebas de tiempo más completas al final, pero solo eche un vistazo a las ganancias de rendimiento que obtenemos con el marco de datos de muestra. Primero, observamos la diferencia en la creación demask

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

Evaluar maskcon el numpyconjunto es ~ 30 veces más rápido. Esto se debe en parte a que la numpyevaluación a menudo es más rápida. También se debe en parte a la falta de sobrecarga necesaria para construir un índice y un pd.Seriesobjeto correspondiente .

A continuación, veremos el momento para cortar con uno maskversus el otro.

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)

Las ganancias de rendimiento no son tan pronunciadas. Veremos si esto se mantiene sobre pruebas más robustas.


maskalternativa 2
Podríamos haber reconstruido el marco de datos también. Hay una gran advertencia al reconstruir un marco de datos: debe tener cuidado dtypesal hacerlo.

En lugar de df[mask]haremos esto

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

Si el marco de datos es de tipo mixto, que es nuestro ejemplo, cuando obtengamos df.valuesla matriz resultante es de dtype objecty, en consecuencia, todas las columnas del nuevo marco de datos serán de dtype object. Por lo tanto, requiere astype(df.dtypes)y elimina cualquier ganancia potencial de rendimiento.

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

Sin embargo, si el marco de datos no es de tipo mixto, esta es una forma muy útil de hacerlo.

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)

Cortamos el tiempo a la mitad.


maskLa alternativa 3
@unutbu también nos muestra cómo usar pd.Series.isinpara dar cuenta de cada elemento de df['A']estar en un conjunto de valores. Esto evalúa lo mismo si nuestro conjunto de valores es un conjunto de un valor, a saber 'foo'. Pero también generaliza para incluir conjuntos de valores más grandes si es necesario. Resulta que esto sigue siendo bastante rápido, aunque es una solución más general. La única pérdida real está en la intuición para aquellos que no están familiarizados con el concepto.

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

Sin embargo, como antes, podemos utilizar numpypara mejorar el rendimiento sin sacrificar prácticamente nada. Usaremosnp.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

El tiempo
incluiré otros conceptos mencionados en otras publicaciones también como referencia.
Código abajo

Cada columna en esta tabla representa un marco de datos de longitud diferente sobre el cual probamos cada función. Cada columna muestra el tiempo relativo tomado, con la función más rápida dada un í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

Notarás que los tiempos más rápidos parecen ser compartidos entre mask_with_valuesymask_with_in1d

res.T.plot(loglog=True)

ingrese la descripción de la imagen aquí

Las funciones

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]

Pruebas

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
Observando el caso especial cuando tenemos un único no objeto dtypepara todo el marco de datos. Código abajo

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

Resulta que la reconstrucción no vale la pena más allá de unos cientos de filas.

spec.T.plot(loglog=True)

ingrese la descripción de la imagen aquí

Las funciones

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
)

Pruebas

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
fuente
66
Fantástica respuesta! Sin embargo, 2 preguntas, i) ¿cómo se .iloc(numpy.where(..))compararía en este esquema? ii) ¿esperaría que las clasificaciones sean las mismas cuando se usan múltiples condiciones?
posdef
3
Para la ejecución de pd.Series.isin, tenga en cuenta que hace uso np.in1dbajo el capó de un escenario específico, usos khash en otros, e implícitamente se aplica una solución de compromiso entre el coste de hash frente al rendimiento en situaciones específicas. Esta respuesta tiene más detalles.
jpp
1
En 9 pantallas llenas, esta es una sobrecarga para un usuario nuevo o incluso intermedio. Puede y debe resumir el tl; dr en el primer párrafo.
smci
@piRSquared Escalado importa ¿le importaría, @piRSquared, para publicar también su experiencia sobre qué tan bien los reales [{P|EXP}TIME] - y [{C|P|EXP}SPACE]- los costos de la utilización de las anteriores formas propuestas de bloque de sintaxis (el procesamiento de arriba hacia abajo las tramas de datos enteros a la vez) crecer , es decir, cuando escalado a algunos ~1E6, ~1E9, ~1E12recuentos de filas? Gracias por mostrarnos la imagen completa, señor. Lecturas de referencia cuantitativa con [min, Avg, MAX, StDev]siempre son bienvenidos, ya que tanto el miny MAXvalores acompañan el Mean/StDevalivio del lote.
user3666197
Excelente respuesta! ¡La consulta resolvió mi problema!
Pavlos Ponos
281

tl; dr

Los pandas equivalentes a

select * from table where column_name = some_value

es

table[table.column_name == some_value]

Múltiples condiciones:

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

o

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

Ejemplo 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

En el código anterior, es la línea df[df.foo == 222]que proporciona las filas según el valor de la columna, 222en este caso.

Múltiples condiciones también son posibles:

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

Pero en ese punto, recomendaría usar la función de consulta , ya que es menos detallada y produce el mismo resultado:

df.query('foo == 222 | bar == 444')
imolit
fuente
55
queryes la única respuesta aquí que es compatible con el método de encadenamiento. Parece que es el pandas análogo a filterin dplyr.
Berk U.
3
Hola, en tu tercer ejemplo (columnas múltiples) creo que necesitas corchetes [no corchetes (en el exterior.
user2739472
2
al principio pensé que |era para AND, pero por supuesto es operador OR ...
O-9
para múltiples condiciones usando AND, se puede hacerdf[condition1][condition2]
Ritwik
1
Dejando esto aquí en caso de que sea útil para alguien: desde 0.25 consulta se puede usar con nombres de columna que tienen espacios en el nombre encerrando el nombre en df.query('`my col` == 124')
comillas invertidas
65

Encuentro que la sintaxis de las respuestas anteriores es redundante y difícil de recordar. Pandas introdujo el query()método en v0.13 y lo prefiero mucho. Para su pregunta, podría hacerdf.query('col == val')

Reproducido 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

También puede acceder a variables en el entorno anteponiendo un @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
fredcallaway
fuente
1
Solo necesita el paquete numexprinstalado.
MERose
44
En mi caso, necesitaba una cita porque val es una cadena. df.query ('col == "val"')
smerlung
28

Más flexibilidad .querycon pandas >= 0.25.0:

Respuesta actualizada de agosto de 2019

Como pandas >= 0.25.0podemos usar el querymétodo para filtrar marcos de datos con métodos pandas e incluso nombres de columnas que tienen espacios. Normalmente, los espacios en los nombres de columna darían un error, pero ahora podemos resolver eso usando un backtick (`) ver 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 .querycon el método str.endswith:

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

Salida

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

También podemos usar variables locales prefijándolas con un @en nuestra consulta:

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

Salida

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

Se pueden lograr resultados más rápidos usando numpy.where .

Por ejemplo, con la configuración de 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

Comparaciones de tiempo:

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

Aquí hay un ejemplo 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
fuente
17

Para seleccionar solo columnas específicas de varias columnas para un valor dado en pandas:

select col_name1, col_name2 from table where column_name = some_value.

Opciones:

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

o

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

Para agregar a esta famosa pregunta (aunque un poco tarde): También puede df.groupby('column_name').get_group('column_desired_value').reset_index()hacer un nuevo marco de datos con una columna específica que tenga un valor particular. P.ej

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)

Ejecute esto da:

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
fuente
Gran respuesta. Solo me gustaría agregar que el segundo (pd.DataFrame) es redundante porque get_group()devolverá automáticamente un marco de datos. También puede decir "drop = True" como parámetro de reset_index(). En otras palabras, se puede acortar a: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Mountain Scott
7

También puedes usar .apply:

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

Realmente funciona en fila (es decir, aplica la función a cada fila).

La salida es

   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

Los resultados son los mismos que los mencionados en @unutbu.

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