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

avatar
szli
12 июня 2013 в 17:42
4395663
14
2781

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

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

SELECT *
FROM table
WHERE colume_name = some_value

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

Источник
debaonline4u
10 июля 2018 в 19:49
0

Проверьте здесь: github.com/debaonline4u/Python_Programming/tree/master/…

I_Al-thamary
5 января 2019 в 08:07
16

Это сравнение с SQL: pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html, где вы можете запускать pandas как SQL.

Jorge Torres
20 апреля 2021 в 06:29
0

вы также можете использовать DFsql для запуска в памяти SQL на фреймах данных pandas medium.com/riselab/… github.com/mindsdb/dfsql

sh37211
12 августа 2021 в 03:10
0

Здесь был приведен поиск соответствия на основе значений из нескольких столбцов. Этот пост - всего лишь о значениях в одном столбце. Предложите редактировать заголовок, чтобы он читался как «значения в столбце», чтобы избежать ложных результатов поиска.

Ответы (14)

avatar
unutbu
12 июня 2013 в 17:44
5293

Чтобы выбрать строки, значение столбца которых равно скаляру, 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)]

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

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, инвертируйте логическую серию, используя ~:

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
szli
12 июня 2013 в 18:12
28

Фактически, df [df ['colume_name'] == some_value] также работает. Но моя первая попытка, df.where (df ['colume_name'] == some_value) не работает ... не знаю почему ...

unutbu
12 июня 2013 в 18:19
16

При использовании df.where(condition) условие должно иметь ту же форму, что и df.

tremendows
27 мая 2014 в 07:32
5

Эти ссылки могут быть очень полезны для многих из вас: pandas.pydata.org/pandas-docs/stable/indexing.html gregreda.com/2013/10/26/working-with-pandas -dataframes

Shane
1 августа 2015 в 00:18
10

К вашему сведению: если вы хотите выбрать строку на основе двух (или более) ярлыков (требующих обоих или любого из них), см. coderhelper.com/questions/31756340/…

qqqwww
20 июня 2018 в 21:05
20

Поскольку df[df['column_name'] == some_value] работает, зачем нам здесь добавлять .loc?

avatar
Erfan
21 апреля 2022 в 09:42
0

Инструкции SQL для DataFrames для выбора строк с помощью DuckDB

С помощью duckdb мы можем запрашивать кадры данных pandas с операторами SQL высокопроизводительным способом.

Поскольку это вопрос Как выбрать строки из DataFrame на основе значений столбца?, а пример в вопросе представляет собой SQL-запрос, этот ответ выглядит логичным в этой теме.

Пример:

In [1]: import duckdb

In [2]: import pandas as pd

In [3]: con = duckdb.connect()

In [4]: df = pd.DataFrame({"A": range(11), "B": range(11, 22)})

In [5]: df
Out[5]:
     A   B
0    0  11
1    1  12
2    2  13
3    3  14
4    4  15
5    5  16
6    6  17
7    7  18
8    8  19
9    9  20
10  10  21

In [6]: results = con.execute("SELECT * FROM df where A > 2").df()

In [7]: results
Out[7]:
    A   B
0   3  14
1   4  15
2   5  16
3   6  17
4   7  18
5   8  19
6   9  20
7  10  21
avatar
L. Astola
16 февраля 2022 в 21:13
0

Отличные ответы. Только когда размер фрейма данных приближается к миллиону строк, многие из методов, как правило, требуют времени при использовании df[df['col']==val]. Я хотел, чтобы все возможные значения «another_column» соответствовали определенным значениям в «some_column» (в данном случае в словаре). Это сработало и быстро.

s=datetime.datetime.now()

my_dict={}

for i, my_key in enumerate(df['some_column'].values): 
    if i%100==0:
        print(i)  # to see the progress
    if my_key not in my_dict.keys():
        my_dict[my_key]={}
        my_dict[my_key]['values']=[df.iloc[i]['another_column']]
    else:
        my_dict[my_key]['values'].append(df.iloc[i]['another_column'])
        
e=datetime.datetime.now()

print('operation took '+str(e-s)+' seconds')```

avatar
lord-hasan
26 ноября 2021 в 06:41
0

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

my_df = df.set_index(column_name)
my_dict = my_df.to_dict('index')

После создания словаря my_dict вы можете пройти через:

if some_value in my_dict.keys():
   my_result = my_dict[some_value]

Если у вас есть повторяющиеся значения в столбце имя_столбца, вы не можете создать словарь. но вы можете использовать:

my_result = my_df.loc[some_value]
avatar
Punnerud
5 января 2021 в 11:43
16

В более новых версиях Pandas на основе документации ( Просмотр данных ):

df[df["colume_name"] == some_value] #Scalar, True/False..

df[df["colume_name"] == "some_value"] #String

Объедините несколько условий, заключив в скобки предложение () и объединив их с & и | (и / или). Как это:

df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]

Другие фильтры

pandas.notna(df["colume_name"]) == True # Not NaN
df['colume_name'].str.contains("text") # Search for "text"
df['colume_name'].str.lower().str.contains("text") # Search for "text", after converting  to lowercase
taotao
9 сентября 2021 в 01:25
0

Спасибо. Что, если я хочу выбрать строки, в которых длина содержимого определенного столбца> 10? Например, я хочу: len (df ["column_name"]> 10, есть ли простой способ сделать это, или я должен зацикливаться, чтобы создать новый DataFrame?

avatar
Erfan
3 августа 2019 в 12:05
46

Больше гибкости при использовании .query с пандами> = 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
Jeff Ellen
13 августа 2021 в 20:46
0

Проголосовали за, потому что приведение .str неочевидно.

avatar
Vahidn
7 декабря 2018 в 17:38
10

Вы также можете использовать .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'])]]
avatar
SP001
7 декабря 2017 в 10:39
28

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

select col_name1, col_name2 from table where column_name = some_value.

Параметры loc:

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

или query:

df.query('column_name == some_value')[[col_name1, col_name2]]
avatar
piRSquared
11 сентября 2017 в 22:14
576

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

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

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

(Примечание по производительности: для каждого базового типа мы можем упростить задачу, используя Pandas API, или мы можем выйти за пределы 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)

Enter image description here

Функции

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)

Enter image description here

Функции

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)
avatar
shivsn
5 июля 2017 в 16:34
29

Более быстрые результаты могут быть достигнуты с помощью 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
avatar
TuanDT
18 ноября 2016 в 12:10
18

Чтобы добавить к этому известному вопросу (хотя и слишком поздно): вы также можете выполнить 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
avatar
fredcallaway
9 февраля 2016 в 01:36
77

Я считаю синтаксис предыдущих ответов избыточным и трудным для запоминания. Pandas представил метод query() в версии 0.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')
avatar
imolit
8 июля 2015 в 15:17
321

tl; dr

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

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

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

df.query('foo == 222 | bar == 444')
Berk U.
23 апреля 2018 в 17:26
7

query - единственный ответ, совместимый с цепочкой методов. Похоже, это аналог панд filter в dplyr.

mgokhanbakal
10 августа 2021 в 09:19
0

Спасибо. Я пробовал несколько способов получить запись. Единственный способ сработал - использовать функцию запроса.

avatar
DataByDavid
13 июня 2013 в 11:49
28

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

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