Как выбрать строки из DataFrame на основе значений столбца?

1965

Как выбрать строки на DataFrameоснове значений в некотором столбце в Python Pandas?

В SQL я бы использовал:

SELECT *
FROM table
WHERE colume_name = some_value

Я попытался просмотреть документацию панд, но не сразу нашел ответ.

szli
источник
Проверьте здесь: github.com/debaonline4u/Python_Programming/tree/master/…
debaonline4u
6
Это сравнение с SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html, где вы можете запускать панд как SQL.
19

Ответы:

3778

Чтобы выбрать строки, значение столбца которых равно скаляру some_value, используйте ==:

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

Чтобы выбрать строки, чье значение столбца является итеративным some_values, используйте isin:

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

Объедините несколько условий с &:

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

Обратите внимание на круглые скобки. Благодаря Питон правила приоритета операций , &связывает более плотно , чем <=и >=. Таким образом, скобки в последнем примере необходимы. Без скобок

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

анализируется как

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

что приводит к значению Истины Серии, является неоднозначной ошибкой .


Чтобы выбрать строки, чье значение столбца не равно some_value , используйте !=:

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

isinвозвращает логическое значение серии, поэтому , чтобы выбрать строки , в которых значение не в some_values, свести на нет булева Series с помощью ~:

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

Например,

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

доходность

     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

Если у вас есть несколько значений, которые вы хотите включить, поместите их в список (или, в более общем случае, любой итеративный) и используйте isin:

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

доходность

     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

Обратите внимание, однако, что если вы хотите сделать это много раз, более эффективно сначала создать индекс, а затем использовать df.loc:

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

доходность

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

или, чтобы включить несколько значений из индекса использования df.index.isin:

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

доходность

       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
источник
19
Фактически, df [df ['colume_name'] == some_value] также работает. Но моя первая попытка, df.where (df ['colume_name'] == some_value) не работает ... не знаю почему ...
szli
13
Когда вы используете df.where(condition), условие должно иметь ту же форму, что и df.
unutbu
3
Эти ссылки могут быть очень полезны для многих из вас: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas-dataframes
tremendows
8
К вашему сведению: если вы хотите выбрать строку на основе двух (или более) меток (требующих либо обе, либо одну), см. Stackoverflow.com/questions/31756340/…
Шейн
7
Так как df[df['column_name'] == some_value]работает, зачем нам .locсюда добавлять ?
qqqwww
314

Есть несколько способов выбора строк во фрейме данных Pandas:

  1. Булева индексация ( df[df['col'] == value])
  2. Позиционная индексация ( df.iloc[...])
  3. Индексирование меток ( df.xs(...))
  4. df.query(...) API

Ниже я покажу вам примеры каждого из них, с советами, когда использовать определенные методы. Предположим, наш критерий - столбец 'A'=='foo'

(Примечание по производительности: для каждого базового типа мы можем упростить задачу, используя API pandas, или мы можем выйти за пределы API, как правило numpy, и ускорить процесс.)


Настройка
Первое, что нам нужно, это определить условие, которое будет служить нашим критерием для выбора строк. Мы начнем со случая OP column_name == some_valueи включим некоторые другие общие случаи использования.

Заимствование из @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. Булева индексация

... Для логического индексирования необходимо найти истинное значение 'A'столбца каждой строки, равное 'foo', а затем использовать эти значения истинности, чтобы определить, какие строки следует сохранить. Обычно мы называем эту серию массивом значений истинности mask. Мы сделаем это и здесь.

mask = df['A'] == '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

Это один из самых простых способов выполнить эту задачу, и если производительность или интуитивность не является проблемой, это должен быть выбранный вами метод. Однако, если производительность является проблемой, то вы можете рассмотреть альтернативный способ создания mask.


2. Позиционная индексация

Позиционная индексация ( df.iloc[...]) имеет свои варианты использования, но это не один из них. Чтобы определить, где нарезать, нам сначала нужно выполнить тот же логический анализ, который мы сделали выше. Это оставляет нам выполнение одного дополнительного шага, чтобы выполнить ту же задачу.

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. Ярлык индексирования

Индексирование меток может быть очень удобным, но в этом случае мы снова делаем больше работы без пользы

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это очень элегантный / интуитивно понятный способ выполнить эту задачу, но часто медленнее. Однако , если вы обратите внимание на временные параметры ниже, для больших данных запрос будет очень эффективным. Больше, чем стандартный подход и такой же величины, как мое лучшее предложение.

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

Я предпочитаю использовать Boolean mask

Фактические улучшения могут быть сделаны путем изменения того, как мы создаем наши Boolean mask.

maskАльтернатива 1
Использовать базовый numpyмассив и отказаться от накладных расходов на создание другогоpd.Series

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

В конце я покажу более полные временные тесты, но просто взглянем на прирост производительности, который мы получаем, используя образец фрейма данных. Во-первых, мы смотрим на разницу в созданииmask

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

Оценка maskс помощью numpyмассива происходит в ~ 30 раз быстрее. Отчасти это связано с тем, что numpyоценка часто происходит быстрее. Это также отчасти связано с отсутствием накладных расходов, необходимых для построения индекса и соответствующего pd.Seriesобъекта.

Далее мы посмотрим на время нарезки одного maskна другое.

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)

Прирост производительности не так выражен. Посмотрим, выдержит ли это более надежное тестирование.


maskВариант 2
Мы могли бы также восстановить фрейм данных. Существует большое предостережение при реконструкции кадра данных - вы должны позаботиться об dtypesэтом!

Вместо этого df[mask]мы сделаем это

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

Если фрейм данных имеет смешанный тип, как в нашем примере, то когда мы получим df.valuesрезультирующий массив, dtype objectи, следовательно, все столбцы нового фрейма данных будут иметь dtype object. Таким образом, требуя astype(df.dtypes)и убивая любые потенциальные выгоды производительности.

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

Однако, если фрейм данных не имеет смешанного типа, это очень полезный способ сделать это.

Данный

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)

Против

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

Мы сократили время пополам.


maskАльтернатива 3
@unutbu также показывает нам, как использовать pd.Series.isinдля учета каждого элемента df['A']нахождения в наборе значений. Это оценивает то же самое, если наш набор значений является набором одного значения, а именно 'foo'. Но это также обобщает включение больших наборов значений, если это необходимо. Оказывается, это все еще довольно быстро, хотя это более общее решение. Единственная реальная потеря заключается в интуитивности для тех, кто не знаком с концепцией.

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

Однако, как и прежде, мы можем использовать его numpyдля повышения производительности, практически ничего не жертвуя. Мы будем использоватьnp.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

Сроки
Я включу другие концепции, упомянутые в других сообщениях, а также для справки.
Код ниже

Каждый столбец в этой таблице представляет фрейм данных различной длины, в котором мы тестируем каждую функцию. Каждый столбец показывает относительное время, с самой быстрой функцией, имеющей базовый индекс 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

Вы заметите , что кратчайшее время , как представляется, распределяются между mask_with_valuesиmask_with_in1d

res.T.plot(loglog=True)

введите описание изображения здесь

функции

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]

тестирование

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)

Особое время
Рассмотрим особый случай, когда у нас есть один необъект dtypeдля всего фрейма данных. Код ниже

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

Оказывается, реконструкция не стоит нескольких сотен рядов.

spec.T.plot(loglog=True)

введите описание изображения здесь

функции

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
)

тестирование

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
источник
6
Фантастический ответ! 2 вопроса, хотя, я) как бы .iloc(numpy.where(..))сравнить в этой схеме? II) вы ожидаете, что рейтинги будут одинаковыми при использовании нескольких условий?
Посеф
3
Для выполнения pd.Series.isin, обратите внимание , что делает использование np.in1dпод капотом в конкретном сценарии использования Хаш в других, и неявно применяется компромисс между стоимостью хеширования по сравнению с производительностью в конкретных ситуациях. Этот ответ более подробно.
jpp
1
На 9 экранах это перегрузка для нового или даже промежуточного пользователя. Вы можете и должны суммировать слова в первом абзаце.
smci
@piRSquared Scaling вопросы вы не возражаете, @piRSquared, также разместить свой опыт о том , как хорошо фактические [{P|EXP}TIME] - и [{C|P|EXP}SPACE]- затраты использования выше предложенных форм блок-синтаксиса (обработка сверху вниз всего dataframes сразу) растут , а именно , когда масштабируется до некоторого количества ~1E6, ~1E9, ~1E12строк? Спасибо, что показали нам всю картину, сэр. [min, Avg, MAX, StDev]Всегда приветствуются количественные значения эталонных тестов , так как minи MAXзначения, и значения сопровождают Mean/StDevрельеф партии.
user3666197
Отличный ответ! Запрос решил мою проблему!
Павлос Понос
281

ТЛ; др

Панды, эквивалентные

select * from table where column_name = some_value

является

table[table.column_name == some_value]

Несколько условий:

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

или

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

Пример кода

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

В приведенном выше коде это строка, df[df.foo == 222]которая дает строки на основе значения столбца, 222в данном случае.

Возможны также несколько условий:

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

Но в этот момент я бы порекомендовал использовать функцию запроса , так как она менее многословна и дает тот же результат:

df.query('foo == 222 | bar == 444')
imolit
источник
5
queryэто единственный ответ, который совместим с цепочкой методов. Кажется, это аналог панд filterв dplyr.
Берк У.
3
Привет, в вашем третьем примере (несколько столбцов) я думаю, что вам нужны квадратные скобки, а [не круглые скобки (снаружи.
user2739472
2
сначала я думал, что |это для AND, но, конечно, это оператор OR ...
O-9
для нескольких условий, используя AND, можно сделатьdf[condition1][condition2]
Ritwik
1
Оставьте это здесь на всякий случай, если это кому-нибудь пригодится: запрос от 0.25 можно использовать с именами столбцов, в имени которых есть пробелы, заключив имя в обратные df.query('`my col` == 124')
черты
65

Я нахожу синтаксис предыдущих ответов излишним и трудным для запоминания. Панда представил query()метод в v0.13, и я предпочитаю его. По вашему вопросу вы могли бы сделатьdf.query('col == val')

Воспроизводится с 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

Вы также можете получить доступ к переменным в среде, добавив @.

exclude = ('red', 'orange')
df.query('color not in @exclude')
fredcallaway
источник
1
Вам нужен только numexprустановленный пакет .
MERose
4
В моем случае мне нужна была цитата, потому что val - это строка. df.query ('col == "val"')
smerlung
28

Больше гибкости при использовании .queryс pandas >= 0.25.0:

Август 2019 обновленный ответ

Поскольку pandas >= 0.25.0мы можем использовать этот queryметод для фильтрации кадров данных с помощью методов pandas и даже имен столбцов, в которых есть пробелы. Обычно пробелы в именах столбцов приводят к ошибке, но теперь мы можем решить эту проблему с помощью обратного символа (`), см. 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

Использование .queryс методом str.endswith:

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

Вывод

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

Также мы можем использовать локальные переменные, добавив префикс @в нашем запросе:

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

Вывод

     Sender email
1  reply@shop.com
2    buy@shop.com
Erfan
источник
26

Более быстрых результатов можно достичь, используя numpy.where .

Например, с настройкой 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

Сроки сравнения:

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
источник
24

Вот простой пример

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
источник
17

Для выбора только определенных столбцов из нескольких столбцов для данного значения в пандах:

select col_name1, col_name2 from table where column_name = some_value.

Опции:

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

или

df.query['column_name' == 'some_value'][[col_name1, col_name2]]
SP001
источник
16

Чтобы добавить к этому известному вопросу (хотя и слишком поздно): Вы также df.groupby('column_name').get_group('column_desired_value').reset_index()можете создать новый фрейм данных с указанным столбцом, имеющим определенное значение. Например

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)

Выполнить это дает:

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
источник
Отличный ответ. Просто хотел бы добавить, что второй (pd.DataFrame) является избыточным, потому get_group()что автоматически вернет фрейм данных. Также вы можете просто сказать «drop = True» в качестве параметра reset_index(). Другими словами, это может быть сокращено до: b_is_two_dataframe = df.groupby('B').get_group('two').reset_index(drop=True)
Гора Скотт
7

Вы также можете использовать .apply:

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

Это на самом деле работает по строкам (то есть применяет функцию к каждой строке).

Выход

   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

Результаты такие же, как при использовании @unutbu

df[[df['B'].isin(['one','three'])]]
Vahidn
источник