0Pricing
Pandas & NumPy Academy · Lekcja

Metoda query()

Zapisywać czytelne wyrażenia filtrujące jako ciągi znaków za pomocą query(), używać zmiennych Pythona wewnątrz zapytań dzięki @ oraz łączyć filtry

Metoda query() to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Dlaczego warto używać query()?

Indeksowanie logiczne w Pandas jest potężne, ale przy łączeniu wielu warunków może stać się rozwlekłe. Metoda query() pozwala zapisywać wyrażenia filtrujące jako zwykłe ciągi znaków, co wiele osób uważa za bardziej czytelne — zwłaszcza osoby mające doświadczenie z SQL. Zamiast df[(df['age'] > 30) & (df['salary'] > 50000)] można napisać df.query('age > 30 and salary > 50000').

Ciąg zapytania jest interpretowany względem nazw kolumn obiektu DataFrame, dlatego nazwy kolumn działają wewnątrz tego ciągu jak nazwy zmiennych.

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Carol', 'Dave'],
    'age': [25, 35, 28, 45],
    'salary': [50000, 90000, 70000, 120000]
})

# Boolean indexing style
result1 = df[(df['age'] > 27) & (df['salary'] > 60000)]

# Equivalent query() style
result2 = df.query('age > 27 and salary > 60000')

print(result2)
#     name  age  salary
# 1    Bob   35   90000
# 2  Carol   28   70000

Reguły składni wewnątrz ciągu zapytania

Wewnątrz ciągu zapytania można używać standardowych operatorów porównania języka Python (>, <, ==, !=, >=, <=) oraz operatorów logicznych and, or, not. W przeciwieństwie do zwykłego indeksowania logicznego można tutaj używać angielskich słów — nie są potrzebne operatory ampersand ani pipe.

Nazwy kolumn zawierające spacje lub kolidujące ze słowami kluczowymi Pythona należy ująć w odwrotne apostrofy: df.query('`first name` == "Alice"').

import pandas as pd

df = pd.DataFrame({
    'product': ['A', 'B', 'C', 'D'],
    'price': [10, 200, 50, 300],
    'in_stock': [True, False, True, True]
})

# Use 'and', 'or', 'not' in query strings
result = df.query('price > 40 and in_stock == True')
print(result)
#   product  price  in_stock
# 2       C     50      True
# 3       D    300      True

Odwoływanie się do zmiennych Pythona za pomocą @

Ważną funkcją query() jest możliwość odwoływania się do zmiennych Pythona z otaczającego zakresu za pomocą prefiksu @. Ułatwia to parametryzowanie filtrów: należy obliczyć próg, zapisać go w zmiennej, a następnie użyć @variable_name w ciągu zapytania zamiast wpisywać wartość na stałe.

Ten wzorzec jest bardzo przydatny w funkcjach, które przyjmują argumenty filtrujące w czasie działania programu.

import pandas as pd

df = pd.DataFrame({
    'city': ['NYC', 'LA', 'Chicago', 'Houston'],
    'population': [8336817, 3979576, 2693976, 2320268]
})

min_pop = 3_000_000  # Python variable

# Use @ to inject the variable into the query
result = df.query('population > @min_pop')
print(result)
#    city  population
# 0   NYC     8336817
# 1    LA     3979576

Łączenie wywołań query()

Ponieważ query() zwraca nowy obiekt DataFrame, można łączyć wiele wywołań query lub zestawiać je z innymi metodami Pandas w potoku. Łączenie umieszcza każdy krok filtrowania w osobnym wierszu, dzięki czemu logika jest łatwa do odczytania, debugowania i modyfikowania.

Można również łączyć query() z metodami takimi jak .groupby(), .sort_values() czy .head(), aby budować zwięzłe potoki analityczne.

import pandas as pd

df = pd.DataFrame({
    'region': ['North', 'South', 'North', 'East', 'South'],
    'year': [2022, 2022, 2023, 2023, 2023],
    'revenue': [100, 200, 150, 80, 300]
})

# Chain two query calls
result = (df
    .query('year == 2023')
    .query('revenue > 100')
    .sort_values('revenue', ascending=False)
)
print(result)
#    region  year  revenue
# 4   South  2023      300
# 2   North  2023      150

Porównanie query() z indeksowaniem logicznym

Obie metody dają ten sam wynik, ale każda z nich sprawdza się w innych sytuacjach. query() świetnie nadaje się do filtrów z wieloma warunkami, które przy indeksowaniu logicznym wymagałyby wielu nawiasów. Indeksowanie logiczne jest lepsze, gdy warunek obejmuje złożone wyrażenia Pythona, takie jak wywołania metod nieobsługiwane w ciągach zapytań.

W większości przypadków wydajność jest podobna; query() może być nieco szybsze dla bardzo dużych obiektów DataFrame, ponieważ wewnętrznie korzysta z biblioteki numexpr.

import pandas as pd

df = pd.DataFrame({
    'A': range(10),
    'B': range(10, 20)
})

# Boolean indexing
result_bool = df[(df['A'] > 2) & (df['B'] < 18) & (df['A'] != 5)]

# Equivalent query — much more readable
result_query = df.query('A > 2 and B < 18 and A != 5')

print(result_query)
#    A   B
# 3  3  13
# 4  4  14
# 6  6  16
# 7  7  17

Porównywanie ciągów znaków w query()

Wartości w kolumnie tekstowej można filtrować wewnątrz ciągu zapytania, umieszczając literał tekstowy w cudzysłowie. Należy użyć podwójnych cudzysłowów dla zewnętrznego ciągu zapytania i pojedynczych cudzysłowów dla wartości tekstowej albo odwrotnie — ważne, aby zachować konsekwencję. Należy pamiętać, że query() nie obsługuje metod .str, takich jak contains(); w takim przypadku należy użyć indeksowania logicznego z .str.

import pandas as pd

df = pd.DataFrame({
    'country': ['USA', 'UK', 'Canada', 'USA', 'Germany'],
    'sales': [400, 150, 200, 600, 300]
})

# Single quotes for the string value inside double-quoted query
result = df.query('country == "USA"')
print(result)
#   country  sales
# 0     USA    400
# 3     USA    600

Używanie operatorów in i not in

Wewnątrz ciągów zapytań Pandas obsługuje operatory in i not in do sprawdzania przynależności, podobnie jak w przypadku list Pythona. Jest to czytelna alternatywa dla łączenia wielu warunków == za pomocą or. Lista wartości jest zapisywana bezpośrednio w ciągu zapytania.

import pandas as pd

df = pd.DataFrame({
    'status': ['active', 'inactive', 'pending', 'active', 'closed'],
    'amount': [100, 200, 50, 300, 150]
})

# Keep rows where status is in a specific list
result = df.query('status in ["active", "pending"]')
print(result)
#     status  amount
# 0   active     100
# 2  pending      50
# 3   active     300

# Exclude certain statuses
excluded = df.query('status not in ["closed", "inactive"]')
print(excluded.shape)  # (3, 2)

Filtrowanie zakresów liczbowych za pomocą query()

Łańcuchowe porównania Pythona, takie jak 10 < price < 500, działają wewnątrz ciągów zapytań, dzięki czemu filtry zakresów są bardzo wyraziste. Nie jest to możliwe przy standardowym indeksowaniu logicznym bez użycia between() lub dwóch osobnych warunków połączonych operatorem &.

import pandas as pd

df = pd.DataFrame({
    'product': ['A', 'B', 'C', 'D', 'E'],
    'price': [5, 50, 150, 300, 500]
})

# Chained comparison — only works inside query()
result = df.query('50 <= price <= 300')
print(result)
#   product  price
# 1       B     50
# 2       C    150
# 3       D    300

Ograniczenia query()

query() jest potężne, ale ma kilka ograniczeń. Nazwy kolumn zawierające spacje lub znaki specjalne wymagają użycia odwrotnych apostrofów. Bardzo złożone wyrażenia Pythona, takie jak funkcje niestandardowe czy logika wielowierszowa, nie są obsługiwane wewnątrz ciągu. Ponadto query() może dawać nieoczekiwane wyniki, jeśli nazwy kolumn kolidują ze słowami kluczowymi Pythona, takimi jak class czy if — je również należy ująć w odwrotne apostrofy.

W przypadku wszystkiego, czego query() nie pozwala wyrazić w czytelny sposób, należy wrócić do standardowego indeksowania logicznego.

import pandas as pd

df = pd.DataFrame({'first name': ['Alice', 'Bob'], 'class': [1, 2]})

# Backtick-quote column names with spaces or reserved words
result = df.query('`first name` == "Alice" and `class` == 1')
print(result)
#   first name  class
# 0      Alice      1

Przykład praktyczny: filtrowanie zamówień

Oto praktyczny przykład łączący query() z odwołaniem do zmiennej oraz z łączeniem metod prowadzącym do groupby. Ten wzorzec — najpierw filtrowanie, a następnie agregowanie — pozwala uniknąć przetwarzania niepotrzebnych wierszy, dzięki czemu kod jest czytelniejszy i działa szybciej na dużych zbiorach danych.

import pandas as pd

orders = pd.DataFrame({
    'region': ['East', 'West', 'East', 'West', 'East'],
    'year': [2023, 2023, 2024, 2024, 2024],
    'revenue': [100, 200, 300, 400, 500]
})

min_year = 2024

# Filter to recent orders in the East region, then sum revenue
summary = (
    orders
    .query('year >= @min_year and region == "East"')
    .groupby('region')['revenue'].sum()
)
print(summary)
# region
# East    800
# Name: revenue, dtype: int64

Najlepsze praktyki dotyczące query() i łączenia metod

Używanie query() w ramach łańcucha metod jest dobrą praktyką we współczesnym kodzie Pandas. Dzięki temu każdy krok potoku przekształceń jest jasny i samodokumentujący się. Cały łańcuch należy ująć w nawiasy, aby można było podzielić go na wiele wierszy bez używania ukośników odwrotnych.

Można łączyć query() z assign() w celu dodawania kolumn, groupby() w celu wykonywania agregacji oraz pipe() w celu używania funkcji niestandardowych, aby budować w pełni czytelne potoki.

import pandas as pd

df = pd.DataFrame({
    'dept': ['Eng', 'HR', 'Eng', 'Sales', 'HR'],
    'salary': [90000, 50000, 120000, 70000, 55000],
    'years': [3, 5, 8, 2, 4]
})

result = (
    df
    .query('years > 2 and dept != "HR"')
    .assign(bonus=lambda x: x['salary'] * 0.1)
    .sort_values('salary', ascending=False)
)
print(result[['dept', 'salary', 'bonus']])
#    dept  salary   bonus
# 2   Eng  120000  12000.0
# 0   Eng   90000   9000.0

Szybki test

Sprawdź swoją wiedzę na temat metody query().

Podsumowanie lekcji

W tej lekcji poznali Państwo następujące zagadnienia: query() przyjmuje wyrażenia filtrujące jako ciągi znaków, dzięki czemu filtry z wieloma warunkami są czytelniejsze; @variable_name wstawia zmienne Pythona do zapytania; można też używać in/not in oraz porównań łańcuchowych, które nie są dostępne przy standardowym indeksowaniu logicznym. Następnie omówimy isin() i between(), służące do zwięzłego filtrowania według przynależności i zakresu.

Często zadawane pytania

Czy lekcja „Metoda query()” jest bezpłatna?

Tak — pełny tekst „Metoda query()” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Metoda query()”?

Zapisywać czytelne wyrażenia filtrujące jako ciągi znaków za pomocą query(), używać zmiennych Pythona wewnątrz zapytań dzięki @ oraz łączyć filtry Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?

Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Metoda query()”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?

Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Indeksowanie boolowskie obiektów DataFrame
  2. Metoda query()
  3. Filtry isin() i between()
  4. Wybieranie kolumn według wzorca
← Powrót do Pandas & NumPy Academy