Наука о данных

10 примеров запросов Pandas, которые упростят вам работу с Pandas Query

Начните легко фильтровать свои данные, используя функцию запроса pandas

Основная фильтрация набора данных с помощью функции запроса pandas!

Анализ данных в Python упрощается благодаря библиотеке Pandas. При выполнении задачи анализа данных часто вам нужно выбрать подмножество данных для более глубокого погружения. И этого можно легко добиться с помощью функции pandas.DataFrame.query().

Поэтому важно понимать, насколько эффективно и действенно вы можете его использовать.

Я перечислил 10 примеров, объясняющих почти все варианты использования, когда вы можете использовать функцию запроса для фильтрации точек данных. В конце концов, вы сможете использовать функцию запроса pandas по мере необходимости без каких-либо проблем.

Вы можете быстро перейти к своему любимому варианту использования с индексом ниже.

· Filtering using Single ConditionExample 1
· Filtering on Multiple ConditionsExample 1Example 2Example 3
· Filtering based on Text ColumnsExample 1
· Simple Math Operation in Pandas QueryExample 1Example 2
· Built-In Functions in Pandas QueryExample 1Example 2
· Filtering based on Date-Time ColumnsExample 1Example 2
· Inplace in Pandas Query Function

📍 Примечание. Я использую самостоятельно созданный Dummy_Sales_Data, который вы можете бесплатно получить в моем репозитории Github в разделе Лицензия MIT!!

Давайте импортируем набор данных в pandas DataFrame — df

import pandas as pd
df = pd.read_csv("Dummy_Sales_Data_v1.csv")
df.head()

Это простой набор данных 9999 x 12, который я создал с помощью Faker в Python 📚

Вы можете загрузить полный блокнот со всеми этими примерами в конце этого чтения!

Прежде чем перейти к примерам, краткий обзор функции запроса в pandas —

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

В серверной части это выражение оценивается с помощью функции eval() в пандах и возвращает подмножество данных или записей, где выражение оценивается как ИСТИНА.

Таким образом, для фильтрации pandas DataFrame все, что вам нужно сделать, это указать условие в функции запроса, как вы увидите в следующих примерах.

Почему вы должны использовать query() поверх нотации pandas DataFrame .loc, .iloc и квадратных скобок [ ]

  • Свойства pandas DataFrame — .loc и .iloc — специально используются для извлечения подмножества набора данных на основе меток и индексов строк и столбцов. Таким образом, на самом деле он не предлагает вам гибкости для фильтрации DataFrame на основе условия.
  • Обозначение скобок [ ] дает вам гибкость для фильтрации DataFrame на основе условия, но синтаксически громоздко писать с несколькими парами квадратных скобок.

С другой стороны, функция pandas query() дает вам возможность извлекать подмножество DataFrame на основе одного или нескольких условий, которые записываются в виде абсолютно простого выражения. Вам действительно не нужно думать или проверять пропущенные скобки! 💯

Теперь, когда вы знаете, почему вам следует предпочесть функцию query() для фильтрации набора данных, давайте начнем с примеров.

Начнем с самого простого варианта использования — фильтрации DataFrame на основе одного условия, то есть условия только для одного столбца.

Фильтрация с использованием одного условия

При фильтрации по одному условию выражение, которое будет оцениваться в функции query(), будет содержать только одно условие. И возвращаемый вывод будет содержать все строки, где это выражение оценивается как TRUE.

Пример 1

Предположим, вы хотите извлечь все строки, где количество равно 95. Таким образом, условие в логической форме можно записать так:

Quantity == 95

📌 Помните, что это условие нужно записать в виде строки, т.е. заключить в двойные кавычки “ ”.

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

df.query("Quantity == 95")

Как просто это выглядит. Он вернул все строки, где количество равно 95.

Что ж, это было довольно просто, и даже вы можете использовать вот такую ​​скобочную нотацию — df[df[“Quantity”]==95].

Но что, если вы хотите включить еще одно условие в тот же столбец??

Это, безусловно, добавляет еще одну пару квадратных скобок в нотацию скобок, делая ее громоздкой и неуправляемой в долгосрочной перспективе. И вот тогда на сцену выходит эффективность query().

Фильтрация по нескольким условиям

Независимо от того, фильтруете ли вы одно или несколько условий, синтаксис query() остается неизменным — записывайте условия в виде строки, заключая их в “ ”.

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

  • AND: возвращает все записи из DataFrame только в том случае, если выполняются оба условия.
  • OR: возвращает все записи из DataFrame, где выполняются одно или оба условия.

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

Пример 1

Предположим, вы хотите выбрать все строки, в которых оба условия — количество равно 95 и цена за единицу — 182 — являются ИСТИННЫМИ.

Итак, вы должны пойти на AND логику. В выражении query() это реализовано с помощью ключевого слова and. 💯

Обратите внимание, что столбец, содержащий цену за единицу, называется UnitPrice(USD).

Итак, условия —

Quantity == 95
UnitPrice(USD) == 182

И выражение станет —

"Quantity == 95 and UnitPrice(USD) == 182"

Чтобы извлечь требуемый набор данных, вы пишете —

df.query("Quantity == 95 and UnitPrice(USD) == 182")

Однако вместо вывода вы получаете KeyError для UnitPrice, как показано ниже. 🚨🚨

Но почему вы получили эту ошибку??

Это связано с тем, что функция query() имеет некоторые ограничения на имена столбцов. И имя столбца UnitPrice(USD) недопустимо для использования в query().

Выражение query() интерпретируетUnitPricee из имени столбцаUnitPrice(USD) как функцию, которая будет работать с переменной USD.

📌 Руководство по запросу() предоставляет быструю альтернативу этой проблеме, упоминание недопустимых имен столбцов в обратных кавычках как — `UnitPrice(USD)`

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

df.query("Quantity == 95 and `UnitPrice(USD)` == 182")

Как видите, есть только 3 записи, когда выполняются оба этих условия.

Однако опять же есть вероятность, что вы забыли упомянуть одну из обратных галочек, и программа выдаст другую Синтаксическую ошибку. Следовательно, одним из самых простых решений является изменение имени столбца, как показано ниже:

df.rename(columns={'UnitPrice(USD)':'UnitPrice', 
                   'Shipping_Cost(USD)':'Shipping_Cost',
                   'Delivery_Time(Days)':'Delivery_Time'},
          inplace=True)

Итак, теперь вы можете получить тот же результат, используя новое имя столбца, что и —

df.query("Quantity == 95 and UnitPrice == 182")

Кроме того, вы также можете получить тот же результат, используя оператор амперсанд &, как —

df.query("Quantity == 95 & UnitPrice == 182")

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

Теперь давайте посмотрим, как вы можете реализовать логику OR.

Пример 2

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

Все, что вам нужно сделать, это использовать ключевое слово or между двумя условиями, как показано ниже:

df.query("Quantity == 95 or UnitPrice == 182")

Он вернул все строки, в которых одно из двух условий было истинным (см. строки со 2 по 5 на рисунке выше), а также строки, в которых оба условия были истинными (строка 1).

Здесь также можно использовать побитовый оператор | вместо ключевого слова or. ✅

Забегая вперед, вы также можете использовать логику NOT в query(), которая возвращает все записи, когда указанное условие в запросе оценивается как FALSE.

Пример 3

Предположим, вы хотите получить все строки, в которых количество не равно 95.

Самый простой ответ — использовать ключевое слово not или оператор отрицания ~ в выражении перед условием, как показано ниже.

df.query("not (Quantity == 95)")

Как видно из вывода, он содержит все строки, в которых количество не равно 95.

Кроме того, условие не всегда должно быть оператором равенства, вы можете выбрать что угодно из ==, !=, >, <, , при определении условия.

Таким образом, вы можете получить тот же вывод, что и логика NOT, используя оператор не-равенства != в условии, как показано ниже.

df.query("Quantity != 95")

Это еще больше сэкономит ваши усилия по написанию (и, возможно, забыв закрыть) дополнительные круглые скобки! И таким образом упрощая query() выражение.

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

Фильтрация на основе текстовых столбцов

При фильтрации на основе текстовых столбцов ваше условие должно сравнивать имя столбца со строкой.

Помните, что ваше выражение query() уже является строкой. Тогда как написать строку внутри другой строки??

📌 Просто заключите значение Text, которое вы хотите использовать в условии, в одинарные кавычки как ‘ ’. Давайте посмотрим на примере, как это сделать.

Пример 1

Предположим, вы хотите получить все записи со статусом «Не отправлено». Вы можете записать это в выражении query() как —

df.query("Status == 'Not Shipped'")

Он возвращает все записи, в которых столбец Статус содержит значение — «Не отправлено».

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

В реальном мире в большинстве случаев условия, которые вы используете для фильтрации DataFrame, включают определенные вычисления. Pandas query() дает вам свободу использовать математику в выражении запроса.

Простая математическая операция в Pandas Query

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

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

Пример 1

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

Это так же просто, как написать выражение на простом английском языке, как показано ниже.

df.query("Shipping_Cost*2 < 50")

Бум! Он вернул все необходимые строки.

Вы также можете включить даже немного сложные вычисления для одного или нескольких столбцов. 💯

Пример 2

Предположим, вы хотите получить все строки, в которых сумма квадрата количества и квадрата стоимости доставки меньше 500.

df.query("Quantity**2 + Shipping_Cost**2 < 500")

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

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

Встроенные функции в Pandas Query

Встроенные функции Python, такие как sqrt(), abs(), factorial(), exp() и многие другие, можно легко использовать в выражении запроса. Вы можете использовать его напрямую, как вы могли бы использовать его в обычных случаях использования.

Пример 1

Получение всех строк, в которых квадратный корень из цены за единицу больше 15. Поэтому здесь будет использоваться встроенная функция — sqrt().

df.query("sqrt(UnitPrice) > 15")

Легко это! Этот запрос возвращает все строки с ценой за единицу больше 225.

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

Пример 2

Получить все записи, в которых «квадратный корень из цены за единицу меньше половины стоимости доставки», настолько просто, что вы можете сделать это с помощью —

df.query("sqrt(UnitPrice) < Shipping_Cost/2")

Таким образом, вы можете фильтровать набор данных, используя несколько условий с разными уровнями сложности. И это тоже с помощью простого запроса. ✅

Все примеры запросов, которые вы видели до сих пор, касались числовых и текстовых столбцов. Однако использование query() не ограничивается только этими типами данных.

Часто вам нужно фильтровать DataFrame на основе значений даты и времени. И функция query() настолько гибкая, что вы можете легко фильтровать набор данных на основе значений даты и времени, как вы можете изучить в разделе ниже.

Фильтрация на основе столбцов даты и времени

Единственное требование для использования функции query() для фильтрации DataFrame по значениям даты и времени: столбец, содержащий эти значения, должен иметь тип данных datetime64[ns]

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

df["OrderDate"] = pd.to_datetime(df["OrderDate"], format="%Y-%m-%d")

Теперь все готово для фильтрации DataFrame с использованием столбца даты и времени в query(). Чтобы извлечь полезную информацию о датах и ​​использовать их в функции query(), очень удобен аксессор dt.

📌 dt — это объект-аксессор, который используется для извлечения свойств даты и времени, подобных ряду дат и времени.

Давайте рассмотрим, какими различными способами вы можете фильтровать набор данных на основе значений даты и времени.

Пример 1

Предположим, вы хотите получить все записи, в которых дата заказа указана в августе. Все, что вам нужно сделать, это —

df.query("OrderDate.dt.month == 8")

Как видите, во всех записях OrderDate стоит в августе. И OrderDate.dt.monthпоказывает, как вы можете использовать метод доступа dt для извлечения только месяца из всего значения даты.

Если продолжить фильтрацию, предположим, что вы хотите получить все заказы за август 2021 года, когда день заказа равен 15 или больше. Вы можете достичь этого с помощью —

df.query("OrderDate.dt.month == 8 and OrderDate.dt.year == 2021 and OrderDate.dt.day >=15")

Хотя это классический пример аксессора dt и объединения нескольких условий в одном столбце, выражение кажется слишком длинным и, следовательно, не рекомендуется.

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

Однако вы можете получить точно такой же результат, написав очень простое выражение, как —

df.query("OrderDate >= '2021-08-15' and OrderDate <= '2021-08-31'")

Кроме того, вы также можете комбинировать условие для столбца «Дата-время» и условие для любого другого столбца в одном выражении. 💯

Пример 2

Например, получить все записи, в которых дата заказа, как в предыдущем примере, и статус «Доставлено», очень просто с помощью выражения запроса:

df.query("OrderDate >= '2021-08-15' and OrderDate <= '2021-08-31' and Status == 'Delivered'")

Он вернул все записи, в которых выражение оценивается как True. Опять же, это всего лишь пример, демонстрирующий, как вы можете комбинировать условия столбца даты и времени и текста в одном запросе.

До сих пор вы указывали только выражение, которое будет оцениваться в функции query(). Однако эта функция также принимает еще один необязательный параметр — inplace.

Inplace в функции запроса Pandas

Во всех примерах вы видите, что df.query() генерирует новый DataFrame. А связано это с тем, что 2-й параметр query() — inplace — по умолчанию установлен в False.

Таким образом, даже после фильтрации DataFrame по нескольким условиям, если вы проверите размер DataFrame, он покажет исходный размер 9999 x 12.

df.shape
# output
(9999, 12)

Таким образом, с inplace=False запрос не изменил исходный набор данных. Если вы хотите внести изменения в исходный DataFrame, просто сделайте inplace=True.

🚨 Но будьте осторожны с inplace=True, так как он перезаписывает исходный DataFrame. Таким образом, нет возможности вернуть исходный DataFrame после выполнения запроса с этой опцией.

Вот и все, что касается фильтрации точек данных с помощью query()!

Я надеюсь, что вы нашли эту статью очень полезной, освежающей, и вы узнали несколько действительно крутых трюков для фильтрации pandas DataFrame. Я уверен, что после прочтения этой статьи вы сможете чаще и свободнее использовать функцию pandas query().

Я использую Python для анализа данных уже более 4 лет и нашел функцию query() наиболее удобной для фильтрации набора данных. Большинство из этих трюков я использую в своей работе каждый день.

Хотите прочитать больше историй на Medium??

💡 Рассмотрите вариант Стать участником Medium, чтобы получить неограниченный доступ к историям на Medium и ежедневным интересным дайджестам Medium. Я получу небольшую часть вашего гонорара и никаких дополнительных затрат для вас.

💡 Не забудьте Подписаться на мою рассылку, чтобы не пропустить новую статью о руководствах, хитростях и советах по науке о данных, SQL и Python.

💡 Вот полный блокнот со всеми примерами.

Спасибо, что прочитали!