Как выбрать строки в DataFrame между двумя значениями в Python Pandas?

102

Я пытаюсь изменить DataFrame, dfчтобы он содержал только строки, для которых значения в столбце closing_priceнаходятся между 99 и 101, и пытаюсь сделать это с помощью приведенного ниже кода.

Однако я получаю сообщение об ошибке

ValueError: значение истинности Серии неоднозначно. Используйте a.empty, a.bool (), a.item (), a.any () или a.all ()

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

df = df[(99 <= df['closing_price'] <= 101)]
user131983
источник
Проблема здесь в том, что вы не можете сравнить скаляр с массивом, отсюда и ошибка, для сравнений вы должны использовать побитовые операторы и заключать их в круглые скобки из-за приоритета операторов
EdChum
df.queryи pd.evalкажутся хорошими для этого варианта использования. Для получения информации о pd.eval()семействе функций, их возможностях и вариантах использования посетите страницу Dynamic Expression Evaluation в pandas, используя pd.eval () .
cs95

Ответы:

109

Вы должны использовать ()для группировки логического вектора, чтобы устранить двусмысленность.

df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]
Цзяньсюнь Ли
источник
178

Рассмотрим также ряды между :

df = df[df['closing_price'].between(99, 101)]
Парфе
источник
6
Опция inclusive=Trueиспользуется по умолчанию в between, так что вы можете запросить вот такdf = df[df['closing_price'].between(99, 101)]
Антон Ермаков
3
это лучший ответ! прекрасная работа!
PEBKAC
Есть ли в пандах функциональность "не между"? Я этого не нахожу.
dsugasa
3
@dsugasa, используйте оператор тильды с between.
Parfait
1
@dsugasa egdf = df[~df['closing_price'].between(99, 101)]
33
23

есть альтернатива получше - используйте метод query () :

In [58]: df = pd.DataFrame({'closing_price': np.random.randint(95, 105, 10)})

In [59]: df
Out[59]:
   closing_price
0            104
1             99
2             98
3             95
4            103
5            101
6            101
7             99
8             95
9             96

In [60]: df.query('99 <= closing_price <= 101')
Out[60]:
   closing_price
1             99
5            101
6            101
7             99

ОБНОВЛЕНИЕ: ответ на комментарий:

Мне здесь нравится синтаксис, но упал при попытке комбинировать с выражением; df.query('(mean + 2 *sd) <= closing_price <=(mean + 2 *sd)')

In [161]: qry = "(closing_price.mean() - 2*closing_price.std())" +\
     ...:       " <= closing_price <= " + \
     ...:       "(closing_price.mean() + 2*closing_price.std())"
     ...:

In [162]: df.query(qry)
Out[162]:
   closing_price
0             97
1            101
2             97
3             95
4            100
5             99
6            100
7            101
8             99
9             95
MaxU
источник
Мне здесь нравится синтаксис, но упал при попытке комбинировать с выражением; df.query ('(mean + 2 * sd) <= closed_price <= (mean + 2 * sd)')
отображение dom
1
@mappingdom, что такое meanи sd? Это названия столбцов?
MaxU
нет, это вычисленное среднее значение и стандартное отклонение, хранящиеся в виде числа с плавающей запятой
отображение dom
@mappingdom, что вы имеете в виду, говоря "хранится"?
MaxU
@mappingdom, я обновил свой пост - это то, о чем вы просили?
MaxU
9

вы также можете использовать .between()метод

emp = pd.read_csv("C:\\py\\programs\\pandas_2\\pandas\\employees.csv")

emp[emp["Salary"].between(60000, 61000)]

Выход

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

Риз.Хан
источник
7
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')

или

mean = closing_price.mean()
std = closing_price.std()

newdf = df.query('@mean <= closing_price <= @std')
авария
источник
3

Если вы имеете дело с несколькими значениями и несколькими входами, вы также можете настроить такую ​​функцию применения. В этом случае фильтрация кадра данных для местоположений GPS, попадающих в определенные диапазоны.

def filter_values(lat,lon):
    if abs(lat - 33.77) < .01 and abs(lon - -118.16) < .01:
        return True
    elif abs(lat - 37.79) < .01 and abs(lon - -122.39) < .01:
        return True
    else:
        return False


df = df[df.apply(lambda x: filter_values(x['lat'],x['lon']),axis=1)]
воробей
источник
1

Вместо этого

df = df[(99 <= df['closing_price'] <= 101)]

Вы должны использовать это

df = df[(df['closing_price']>=99 ) & (df['closing_price']<=101)]

Мы должны использовать побитовые логические операторы NumPy |, &, ~, ^ для составления запросов. Кроме того, круглые скобки важны для приоритета оператора.

Для получения дополнительной информации вы можете перейти по ссылке: Сравнения, маски и логическая логика.

Рушаб Агарвал
источник