Pandas Cheat Sheet: ściąga z pandas
Ostatnia aktualizacja
Tworzenie DataFrame'u
Małe DataFrame'y budowane ręcznie: do przykładów, testów i tabel pomocniczych.
| Zadanie | Kod |
|---|---|
| Import pandas i NumPy | import pandas as pd
import numpy as np |
| Ze słownika kolumn | df = pd.DataFrame({"name": ["Ada", "Ben"], "age": [36, 28]}) |
| Z listy wierszy | pd.DataFrame([{"name": "Ada", "age": 36}, {"name": "Ben", "age": 28}]) |
| Z tablicy NumPy | pd.DataFrame(np.arange(6).reshape(3, 2), columns=["x", "y"]) |
| Series z etykietami | s = pd.Series([3, 5, 2], index=["a", "b", "c"]) |
| Zakres dat | pd.date_range("2026-01-01", periods=7, freq="D") |
Odczyt i zapis plików
Jedno wywołanie wczytuje plik do DataFrame'u, a drugie zapisuje go z powrotem.
| Zadanie | Kod |
|---|---|
| Wczytaj plik CSV | df = pd.read_csv("sales.csv") |
| Tylko wybrane kolumny, z prawdziwymi datami | pd.read_csv("sales.csv", usecols=["date", "city", "sales"], parse_dates=["date"]) |
| Kolumna jako indeks | pd.read_csv("sales.csv", index_col="id") |
| Tabulator lub inny separator | pd.read_csv("sales.tsv", sep="\t") |
| Dodatkowe znaczniki jako braki | pd.read_csv("sales.csv", na_values=["n/a", "-"]) |
| Tylko pierwsze wiersze | pd.read_csv("sales.csv", nrows=1000) |
| Arkusz Excela (wymaga openpyxl) | pd.read_excel("report.xlsx", sheet_name="2026") |
| Rekordy JSON | pd.read_json("records.json") |
| Odczyt z bazy SQL | pd.read_sql("SELECT * FROM orders", conn) |
| Zapis CSV bez indeksu | df.to_csv("clean.csv", index=False) |
| Zapis do Excela lub Parquet | df.to_excel("clean.xlsx", index=False), df.to_parquet("clean.parquet") |
Przeglądanie danych
Pierwsze wywołania przy każdym nowym zbiorze danych.
| Zadanie | Kod |
|---|---|
| Pierwsze i ostatnie wiersze | df.head(), df.tail(3) |
| Liczba wierszy i kolumn | df.shape # (6, 7) |
| Typy kolumn i liczba wartości niepustych | df.info() |
| Statystyki kolumn liczbowych | df.describe() |
| Podsumowanie wszystkich kolumn | df.describe(include="all") |
| Nazwy i typy kolumn | df.columns, df.dtypes |
| Liczność każdej wartości | df["city"].value_counts() |
| Udział każdej wartości | df["city"].value_counts(normalize=True) |
| Unikalne wartości i ich liczba | df["city"].unique(), df["city"].nunique() |
| Braki w każdej kolumnie | df.isna().sum() |
| Losowa próbka wierszy | df.sample(3, random_state=0) |
| Korelacja kolumn liczbowych | df.corr(numeric_only=True) |
Wybieranie kolumn i wierszy
loc wybiera po etykiecie i obejmuje koniec wycinka. iloc wybiera po pozycji i go pomija.
| Zadanie | Kod |
|---|---|
| Jedna kolumna jako Series | df["age"] |
| Kilka kolumn jako DataFrame | df[["name", "age"]] |
| Wiersze i kolumny po etykiecie | df.loc[0:2, ["name", "age"]] |
| Wiersze i kolumny po pozycji | df.iloc[0:2, 0:3] |
| Jedna wartość | df.at[0, "age"], df.iat[0, 3] |
| Ostatni wiersz | df.iloc[-1] |
| Kolumny jednego typu | df.select_dtypes(include="number") |
| Kolumny tekstowe (pandas 3) | df.select_dtypes(include="str") |
| Kolumny po fragmencie nazwy | df.filter(like="sal"), df.filter(regex="^(age|salary)$") |
| Wyszukiwanie wierszy po kolumnie | df.set_index("name").loc["Ada", "salary"] |
| Powrót do indeksu 0, 1, 2 | df.reset_index(drop=True) |
| Usuń kolumny lub wiersze | df.drop(columns=["email"]), df.drop(index=[0, 1]) |
Filtrowanie wierszy
Każdy warunek ujmij w nawiasy i łącz je przez & (i), | (lub) oraz ~ (nie).
| Zadanie | Kod |
|---|---|
| Wiersze spełniające warunek | df[df["age"] > 30] |
| Oba warunki | df[(df["age"] > 30) & (df["city"] == "Oslo")] |
| Jeden z warunków | df[(df["city"] == "Oslo") | (df["salary"] > 6000)] |
| Wartość z listy | df[df["city"].isin(["Oslo", "Rome"])] |
| Wartość spoza listy | df[~df["city"].isin(["Oslo", "Rome"])] |
| Między dwiema wartościami, z końcami | df[df["age"].between(30, 40)] |
| Filtr z tekstem zapytania | df.query("age > 30 and city == 'Oslo'") |
| Zmienna w zapytaniu | min_age = 30
df.query("age > @min_age") |
| Tekst zawiera | df[df["name"].str.contains("e", case=False)] |
| Wartości brakujące lub obecne | df[df["age"].isna()], df[df["age"].notna()] |
| Filtruj wiersze i wybierz kolumny | df.loc[df["age"] > 30, ["name", "salary"]] |
| Pierwsze lub ostatnie n wierszy | df.nlargest(3, "salary"), df.nsmallest(2, "age") |
| Wiersze z powtórzoną wartością | df[df.duplicated(subset=["city"], keep=False)] |
Sortowanie i ranking
| Zadanie | Kod |
|---|---|
| Sortuj po kolumnie | df.sort_values("salary") |
| Od największych | df.sort_values("salary", ascending=False) |
| Sortuj po kilku kolumnach | df.sort_values(["city", "salary"], ascending=[True, False]) |
| Braki na początku | df.sort_values("age", na_position="first") |
| Sortuj po indeksie | df.sort_index() |
| Ranking, 1 to najwyższa | df["salary"].rank(ascending=False) |
Dodawanie i zmiana kolumn
Operacje na całych kolumnach są szybkie. Po apply sięgaj tylko wtedy, gdy żadna wbudowana metoda nie wystarczy.
| Zadanie | Kod |
|---|---|
| Nowa kolumna z innych | df["bonus"] = df["salary"] * 0.1 |
| Dodaj kolumnę w łańcuchu | df.assign(bonus=lambda d: d["salary"] * 0.1) |
| Wartość zależna od warunku | df["level"] = np.where(df["age"] >= 40, "senior", "junior") |
| Wartość zależna od kilku warunków | df["band"] = np.select([df["age"] < 30, df["age"] < 45], ["young", "mid"], default="senior") |
| Zmień wartości tam, gdzie warunek jest spełniony | df.loc[df["city"] == "Lima", "salary"] = 4000 |
| Mapuj wartości słownikiem | df["country"] = df["city"].map({"Oslo": "NO", "Rome": "IT", "Lima": "PE"}) |
| Funkcja na kolumnie | df["salary"].apply(lambda x: round(x, -3)) |
| Funkcja na każdej komórce | df[["age", "salary"]].map(lambda x: x / 1000) |
| Zmień nazwy kolumn | df.rename(columns={"salary": "pay"}) |
| Zmień typ kolumny | df["salary"].astype("float64") |
| Tekst na liczby, błędne na NaN | pd.to_numeric(s, errors="coerce") |
| Liczby w przedziały z etykietami | pd.cut(df["age"], bins=[0, 30, 45, 120], labels=["young", "mid", "senior"]) |
| Liczby w równe grupy | pd.qcut(df["salary"], q=4, labels=False) |
| Pętla po wierszach (wolna, ostateczność) | for row in df.itertuples():
print(row.name, row.salary) |
Braki danych i czyszczenie
Brakujące liczby widać jako NaN, brakujące daty jako NaT. Każde z tych wywołań zwraca nowy obiekt, więc przypisz wynik.
| Zadanie | Kod |
|---|---|
| Odsetek braków w każdej kolumnie | df.isna().mean() |
| Usuń wiersze z jakimkolwiek brakiem | df.dropna() |
| Usuń wiersze bez kluczowej kolumny | df.dropna(subset=["age"]) |
| Uzupełnij wartością dla każdej kolumny | df.fillna({"age": df["age"].median()}) |
| Uzupełnij z poprzedniego lub następnego wiersza | df["age"].ffill(), df["age"].bfill() |
| Uzupełnij luki interpolacją | df["age"].interpolate() |
| Znaczniki na braki | df.replace(["n/a", "-", ""], np.nan) |
| Usuń zduplikowane wiersze | df.drop_duplicates() |
| Zostaw ostatni wiersz dla klucza | df.drop_duplicates(subset=["city"], keep="last") |
| Uporządkuj nazwy kolumn | df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_") |
| Przytnij skrajne wartości | df["salary"].clip(lower=4000, upper=6000) |
| Typ category dla powtarzalnego tekstu | df["city"] = df["city"].astype("category") |
Kolumny tekstowe (.str)
W pandas 3 kolumny tekstowe domyślnie dostają dtype str. Metody .str działają na całej kolumnie, a braki pozostają brakami.
| Zadanie | Kod |
|---|---|
| Wielkie, małe litery lub tytułowe | df["name"].str.upper(), df["name"].str.lower(), df["name"].str.title() |
| Usuń spacje z brzegów | df["name"].str.strip() |
| Zamień tekst | df["email"].str.replace("mail.com", "example.com") |
| Zamień wyrażeniem regularnym | df["email"].str.replace(r"@.*", "", regex=True) |
| Zawiera, zaczyna się od | df["name"].str.contains("a"), df["name"].str.startswith("E") |
| Długość każdej wartości | df["name"].str.len() |
| Pierwsze znaki | df["name"].str[:2] |
| Podziel na kolumny | df["email"].str.split("@", expand=True) |
| Wyciągnij grupą regex | df["email"].str.extract(r"@(\w+)") |
| Połącz kolumny tekstowe | df["name"] + " (" + df["city"] + ")" |
| Dopełnij liczby zerami | df["salary"].astype("str").str.zfill(6) |
| Nowy dtype tekstowy | df["name"].dtype # str |
Daty i czas
Akcesor .dt działa na kolumnach datetime. Posortowany indeks dat (ts poniżej) pozwala wycinać po tekście i robić resampling.
| Zadanie | Kod |
|---|---|
| Zamień kolumnę na datetime | df["date"] = pd.to_datetime(df["date"]) |
| Parsowanie z dokładnym formatem | pd.to_datetime(["03/01/2026", "15/01/2026"], format="%d/%m/%Y") |
| Rok, miesiąc, nazwa dnia tygodnia | df["date"].dt.year, df["date"].dt.month, df["date"].dt.day_name() |
| Grupuj daty po miesiącach | df["date"].dt.to_period("M") |
| Dni między dwiema datami | (pd.Timestamp("2026-12-31") - df["date"]).dt.days |
| Dodaj dni lub miesiące | df["date"] + pd.Timedelta(days=30), df["date"] + pd.DateOffset(months=1) |
| Wiersze z zakresu dat | df[df["date"].between("2021-01-01", "2022-12-31")] |
| Indeks dat, wycinany tekstem | ts = df.set_index("date").sort_index()
ts.loc["2021":"2022"] |
| Suma na miesiąc | ts["salary"].resample("ME").sum() |
Średnia tygodniowa; "QE" to kwartały, "YE" lata | ts["salary"].resample("W").mean() |
| Średnia krocząca | ts["salary"].rolling(3).mean() |
| Zmiana względem poprzedniego wiersza | ts["salary"].diff(), ts["salary"].pct_change() |
| Przesuń wartości o wiersz w dół | ts["salary"].shift(1) |
| Suma narastająca | ts["salary"].cumsum() |
| Ustaw i przelicz strefy czasowe | ts.index.tz_localize("UTC").tz_convert("Europe/Oslo") |
Grupowanie i agregacja
groupby dzieli wiersze według klucza, stosuje funkcję do każdej grupy i łączy wyniki.
| Zadanie | Kod |
|---|---|
| Średnia w grupie | df.groupby("city")["salary"].mean() |
| Kilka statystyk naraz | df.groupby("city")["salary"].agg(["mean", "max", "count"]) |
| Nazwane kolumny wyniku | df.groupby("city").agg(avg_pay=("salary", "mean"), people=("name", "count")) |
| Grupuj po dwóch kolumnach | df.groupby(["city", "team"])["salary"].sum() |
| Klucze jako kolumny | df.groupby("city", as_index=False)["salary"].mean() |
| Liczba wierszy w grupie | df.groupby("city").size() |
| Wynik grupy w każdym wierszu | df["city_avg"] = df.groupby("city")["salary"].transform("mean") |
| Zostaw tylko niektóre grupy | df.groupby("city").filter(lambda g: len(g) >= 2) |
| Wiersz z maksimum w grupie | df.loc[df.groupby("city")["salary"].idxmax()] |
| Pierwsze n wierszy w grupie | df.sort_values("salary", ascending=False).groupby("city").head(2) |
| Numeruj wiersze w każdej grupie | df.groupby("city").cumcount() |
| Pętla po grupach | for city, group in df.groupby("city"):
print(city, len(group)) |
| Filtruj, grupuj i sortuj w jednym łańcuchu | (df.query("age > 30")
.groupby("city", as_index=False)
.agg(avg_pay=("salary", "mean"))
.sort_values("avg_pay", ascending=False)) |
Tabele przestawne i przekształcanie
Dane długie mają jeden wiersz na obserwację. Dane szerokie rozkładają jedną zmienną na kolumny.
| Zadanie | Kod |
|---|---|
| Tabela przestawna | df.pivot_table(index="city", columns="team", values="salary", aggfunc="mean", fill_value=0) |
| Tabela przestawna z sumami | df.pivot_table(index="city", values="salary", aggfunc="sum", margins=True) |
| Zlicz kombinacje | pd.crosstab(df["city"], df["team"]) |
| Udziały w wierszu | pd.crosstab(df["city"], df["team"], normalize="index") |
| Z szerokiego na długi | long = df.melt(id_vars="name", value_vars=["age", "salary"], var_name="field", value_name="value") |
| Z długiego na szeroki | long.pivot(index="name", columns="field", values="value") |
| Wewnętrzny poziom indeksu na kolumny | df.groupby(["city", "team"])["salary"].sum().unstack(fill_value=0) |
| Jeden wiersz na element listy | pd.DataFrame({"id": [1, 2], "tags": [["a", "b"], ["c"]]}).explode("tags") |
| Kodowanie one-hot kolumny | pd.get_dummies(df["team"], prefix="team") |
| Zamień wiersze z kolumnami | df.T |
Łączenie DataFrame'ów
concat układa ramki jedna na drugiej, a merge łączy je po kolumnach kluczy, tak jak SQL.
| Zadanie | Kod |
|---|---|
| Dołącz wiersze | pd.concat([df_2025, df_2026], ignore_index=True) |
| Obok siebie | pd.concat([left, right], axis=1) |
| Join po kolumnie klucza | orders.merge(customers, on="customer_id", how="left") |
| Rodzaje złączeń | how="inner", "left", "right", "outer" |
| Klucze o różnych nazwach | orders.merge(users, left_on="customer_id", right_on="id") |
| Sprawdź złączenie i oznacz źródło wierszy | orders.merge(customers, on="customer_id", how="left", validate="many_to_one", indicator=True) |
| Join po indeksie | left.join(right, how="inner") |
| Wiersze bez dopasowania w drugiej tabeli | orders[~orders["customer_id"].isin(customers["customer_id"])] |
Wykresy w pandas
pandas rysuje za pomocą Matplotlib. Każde wywołanie wykresu zwraca obiekt Matplotlib ax, więc możesz dalej go stylować.
| Zadanie | Kod |
|---|---|
| Wykres liniowy serii | ts["salary"].plot() |
| Wykres liniowy z dwóch kolumn | df.plot(x="date", y="salary") |
| Wykres słupkowy podsumowania | df.groupby("city")["salary"].mean().plot.bar() |
| Posortowane słupki poziome | df["city"].value_counts().sort_values().plot.barh() |
| Histogram | df["salary"].plot.hist(bins=20) |
| Wykres punktowy | df.plot.scatter(x="age", y="salary") |
| Wykres pudełkowy dla grup | df.boxplot(column="salary", by="city") |
| Tytuł i opis osi | ax = df.plot(x="date", y="salary", title="Salary")
ax.set_ylabel("EUR") |
| Pokaż lub zapisz wykres | plt.show(), ax.figure.savefig("salary.png", dpi=150) |
pandas 3: stare zapisy i co pisać teraz
Kod skopiowany ze starszych tutoriali często w pandas 3 rzuca błąd albo ostrzeżenie. Używaj zapisów z kolumny pandas 3.
| Zadanie | pandas 3 | Stary zapis |
|---|---|---|
| Funkcja na każdej komórce | df.map(f) | df.applymap(f) |
| Uzupełnij z poprzedniego wiersza | df.ffill() | df.fillna(method="ffill") |
| Dodaj wiersze | pd.concat([df, new_rows]) | df.append(new_rows) |
| Resampling na koniec miesiąca | ts["salary"].resample("ME").sum() | resample("M") |
| Daty co godzinę | pd.date_range("2026-01-01", periods=24, freq="h") | freq="H" |
| Ustaw jedną wartość | df.loc[0, "age"] = 37 | df["age"][0] = 37 |
| Zmień przefiltrowany podzbiór | high = df[df["salary"] > 5000]
high["salary"] = 0 | high = df[df["salary"] > 5000].copy() |
| Czy to kolumna tekstowa? | df["name"].dtype == "str" | df["name"].dtype == object |
Kod pandas, po który analityk danych sięga na co dzień, pogrupowany według zadań: tworzenie i wczytywanie danych, przeglądanie, wybieranie i filtrowanie wierszy, dodawanie kolumn, czyszczenie braków, praca z tekstem i datami, grupowanie i agregacja, przekształcanie, łączenie i wykresy. Każdy wiersz to krótki fragment kodu do wklejenia i jedno zdanie o tym, co robi.
Wszystko tutaj jest napisane dla pandas 3, wersji, której używa Coddy: kolumny tekstowe mają nowy dtype str, Copy-on-Write jest zawsze włączony, a usunięte API, takie jak applymap i fillna(method=...), pojawiają się tylko w tabeli starych zapisów. Przykłady korzystają z DataFrame'u df z kolumnami name, city, team, age, salary, date i email. Dopiero zaczynasz z Pythonem? Zajrzyj do ściągi z Pythona i Python playground, a obok tej ściągi trzymaj też ściągi z NumPy, Matplotlib i scikit-learn.
FAQ: ściąga z pandas
Czy ta ściąga z pandas jest darmowa?
Którą wersję pandas obejmuje ta ściąga?
str, Copy-on-Write jest zawsze włączony, a wywołania usunięte w pandas 3 (applymap, fillna(method=...), append, aliasy częstotliwości M i H) pojawiają się tylko w ostatniej tabeli, obok tego, co pisać zamiast nich. Prawie każdy fragment działa też w pandas 2.2, poza wierszami, które opierają się na dtype str lub na Copy-on-Write.Czym różni się loc od iloc?
loc wybiera po etykiecie, czyli po wartościach indeksu i nazwach kolumn, a wycinek taki jak df.loc[0:2] obejmuje swój koniec. iloc wybiera po pozycji całkowitej, jak lista w Pythonie, więc df.iloc[0:2] zwraca dwa pierwsze wiersze i pomija koniec. Użyj loc z warunkiem, żeby w jednym kroku przefiltrować wiersze i wybrać kolumny: df.loc[df["age"] > 30, ["name"]].Jak przefiltrować DataFrame po kilku warunkach?
& (i), | (lub) oraz ~ (nie): df[(df["age"] > 30) & (df["city"] == "Oslo")]. Pythonowe and i or nie działają na całych kolumnach. Przy długich filtrach df.query("age > 30 and city == 'Oslo'") jest czytelniejsze.Czym różnią się merge, join i concat?
merge łączy dwa DataFrame'y po kolumnach kluczy, jak join w SQL, z how="inner", "left", "right" albo "outer". join to skrót, który łączy po indeksie. concat w ogóle nie dopasowuje kluczy: układa ramki jedna na drugiej albo obok siebie z axis=1.Dlaczego moje przypisanie nie zmienia DataFrame'u?
df["age"][0] = 37, zmienia tymczasowy obiekt i nie rusza df. Zapisz to jako jedno wywołanie loc: df.loc[0, "age"] = 37. Metody takie jak dropna i fillna też zwracają nowy obiekt, więc przypisz wynik.