Pandas to biblioteka w języku Python, stworzona z myślą o łatwiej i efektywnej analizie danych. Możliwości biblioteki Pandas:
- Wczytywanie i zapisywanie danych w różnych formatach: CSV, Excel, JSON i SQL
- Przekształcanie i czyszczenie danych
- **Analiza statystyczna
- Wizualizacja danych
Pandas pozwala na szybkie, elastyczne i intuicyjne operacje na danych, zarówno jednowymiarowych (Series), jak i wielowymiarowych (DataFrame).
DataFrame przypomina dwuwymiarową tablicę NumPy, ale ma etykiety kolumn i wierszy, a każda kolumna może zawierać różne typy danych. Wyodrębniając pojedynczą kolumnę lub wiersz z DataFrame, otrzymujemy jednowymiarowy obiekt Series, który przypomina jednowymiarową tablicę NumPy z etykietami.
Wczytywanie i zapis danych:
Wczytywanie danych z pliku CSV:
import pandas as pd
df = pd.read_csv('plik.csv')
Zapis danych jako pliku CSV:
df.to_csv('nowy_plik.csv', index=False)
Wczytywanie danych z pliku Excel:
df = pd.read_excel('plik.xlsx')
Wczytywanie danych z pliku JSON:
df = pd.read_json('plik.json')
Podstawowe Operacje na DataFrame:
Metody | Opis |
---|---|
df.tail() |
Wyświetla ostatnich 5 wierszy z DataFrame, aby szybko przejrzeć końcówkę danych. |
df.info() |
Zwraca szczegółowe informacje o strukturze DataFrame, w tym liczbie wierszy, kolumn, typach danych i brakujących wartościach. |
df.describe() |
Generuje podstawowe statystyki opisowe (np. średnia, odchylenie standardowe, min, max) dla danych numerycznych w DataFrame. |
df.shape |
Zwraca krotkę z liczbą wierszy i kolumn w DataFrame. |
df.dtypes |
Wyświetla typ danych każdej kolumny w DataFrame, co pomaga zrozumieć strukturę danych. |
df.columns |
Wyświetla listę nazw kolumn, ułatwiając szybkie sprawdzenie, jakie dane są dostępne w DataFrame. |
print(df.tail())
print(df.info())
print(df.describe())
print(df.shape)
print(df.dtypes)
print(df.columns)
Przekształcanie, czyszczenie i transformacje danych:
Wyświetlanie i zliczanie unikalnych wartości w kolumnie :
print(df.['nazwa_kolumny'].unique())
print(df.['nazwa_kolumny'].value_counts())
Usuwanie wybranej kolumny:
df.drop(columns=['nazwa_kolumny'], inplace=True)
W zastosowaniach statystycznych dane niedostępne mogą być danymi, które nie istnieją, lub danymi które istnieją, ale nie zostały zaobserwowane (np. z powodu problemu wynikającego ze sposobu zbierania danych).
Podczas oczyszczania danych przed przeprowadzeniem ich analizy często warto przeprowadzić analizę samych brakujących wartości.
Argument | Opis |
---|---|
dropna | Filtruje etykiety osi na podstawie występowania brakujących danych; możliwe jest zdefiniowanie zmiennych wartości progowych określających liczbę tolerowanych brakujących danych. |
fillna | Wypełnia brakujące dane jakimiś wartościami lub robi to za pomocą metody interpolacji, takiej jak np. "ffill" lub "bfill". |
isna | Zwraca wartości logiczne określające miejsce występowania brakujących wartości. |
notna | Negacja isna. Zwraca True, jeżeli wartość istnieje, a False w przeciwnym wypadku. |
Wyświetlanie brakujących danych:
print(df.isnull().sum())
Usuwanie brakujących wartości
df.dropna(inplace=True)
Uzupełnianie brakujących wartości
df.fillna(0, inplace=True)
Statystyka opisowa pozwala na podsumowanie zbiorów danych za pomocą miar ilościowych. Dla przykładu prostą statystyką opisową jest liczba punktów danych. Innymi popularnymi przykładami są średnie, mediany lub dominanty. Obiekty DataFrame i Series zapewniają wygodny dostęp do statystyk opisowych za pomocą metod takich jak sum, mean i count.
Metoda | Opis |
---|---|
mean() |
Oblicza średnią dla kolumn numerycznych. |
sum() |
Sumuje wartości w kolumnach. |
std() |
Oblicza odchylenie standardowe. |
describe() |
Zwraca szczegółowe podsumowanie statystyczne dla kolumn numerycznych. |
groupby() |
Grupuje dane na podstawie wskazanej kolumny. |
agg() |
Pozwala zastosować różne funkcje agregujące (np. mean , sum ). |
import pandas as pd
# Dane z firmy w działach w róznych miastach
data = {
"Miasto": ["Warszawa", "Kraków", "Poznań", "Wrocław", "Gdańsk", "Sopot", "Zakopane", "Łódź"],
"Kawa (litry)": [200.5, 300.1, 280.3, 400.4, 310.2, 270.6, 150.3, 320.9],
"Brak snu (godziny)": [50, 100, 90, 130, 80, 95, 40, 85],
"Dział": ["Produkcja", "HR", "IT", "Produkcja", "Marketing", "IT", "Produkcja", "HR"]
}
df = pd.DataFrame(data)
opis = df.describe()
# Grupowanie danych na podstawie działu
grupa_dzial = df.groupby("Dział").agg({
"Kawa (litry)": ["mean", "sum"],
"Brak snu (godziny)": ["mean", "sum"]
})
print("=== Statystyka opisowa dla pracowników ===\n")
print(opis)
print("\n=== Średnie spożycie kawy oraz brak snu w różnych działach ===\n")
print(grupa_dzial)
# Szukamy działu, w którym pracownicy potrzebują najwięcej kawy
dzial_max_kawa = df.groupby("Dział")["Kawa (litry)"].sum().idxmax()
print(f"\nNajwięcej kawy pije dział: {dzial_max_kawa})
1.
Kawa (litry) Brak snu (godziny)
count 8.000000 8.000000
mean 279.162500 83.750000
std 71.570789 28.643055
min 150.300000 40.000000
25% 255.225000 77.500000
50% 290.250000 87.500000
75% 312.675000 95.000000
max 400.400000 130.000000
2.
Kawa (litry) Brak snu (godziny)
mean sum mean sum
Dział
HR 310.50 621.0 92.500000 185
IT 275.45 550.9 92.500000 185
Marketing 310.20 310.2 80.000000 80
Produkcja 250.40 751.2 73.333333 220
Filtrowanie wierszy, gdzie wartość w kolumnie 'wiek' jest większa niż 25:
df_filtered = df[df['wiek'] > 25]
Filtrowanie wierszy, gdzie wartość w kolumnie 'wiek' jest większa niż 25 i w kolumnie 'miasto' jest równa 'Poznań':
df_filtered = df[(df['wiek'] > 25) & (df['miasto'] == 'Poznań')]
Grupowanie danych i obliczanie statystyk dla każdej grupy:
grouped = df.groupby('nazwa_kolumny').mean()
Sortowanie danych według wybranej kolumny:
df_sorted = df.sort_values(by='nazwa_kolumny', ascending=True)
Zmian nazw kolumn:
df.rename(columns={'stara_nazwa': 'nowa_nazwa'}, inplace=True)
Mapowanie polega na zastąpieniu jednej wartości inną, np. w oparciu o słownik.
W przykładzie mamy dane dotyczące produktów mięsnych, a my chcemy dodać kolumnę z informacją o zwierzęciu, z którego pochodzi dany produkt.
import pandas as pd
data = pd.DataFrame({
'food': ['bacon', 'pulled pork', 'bacon', 'Pastrami', 'corned beef', 'Bacon', 'pastrami', 'honey ham', 'nova lox'],
'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]
})
meat_to_animal = {
'bacon': 'pig',
'pulled pork': 'pig',
'pastrami': 'cow',
'corned beef': 'cow',
'honey ham': 'pig',
'nova lox': 'salmon'
}
# Zmapowanie typu mięsa na zwierzę
data['animal'] = data['food'].str.lower().map(meat_to_animal)
print(data)
Rezultat:
food | ounces | animal | |
---|---|---|---|
0 | bacon | 4.0 | pig |
1 | pulled pork | 3.0 | pig |
2 | bacon | 12.0 | pig |
3 | Pastrami | 6.0 | cow |
4 | corned beef | 7.5 | cow |
5 | Bacon | 8.0 | pig |
6 | pastrami | 3.0 | cow |
7 | honey ham | 5.0 | pig |
8 | nova lox | 6.0 | salmon |
Szeregi czasowe to jedna z kluczowych funkcjonalności Pandas, zwłaszcza gdy pracujemy z danymi finansowymi, meteorologicznymi czy jakimikolwiek danymi zależnymi od czasu
Zacznijmy od prostego przykładu pracy z datami, które przekształcimy z łańcuchów znaków na znacznik czasu.
datetime
: Podstawowe narzędzia pracy z datamiModuł datetime
w Pythonie pozwala na tworzenie, manipulowanie i formatowanie dat oraz czasu. Używając go, możemy wykonywać podstawowe operacje na obiektach daty i czasu.
Aby utworzyć obiekt daty w Pythonie, korzystamy z klasy datetime
:
import pandas as pd
# Konwersja daty z tekstu na obiekt Timestamp
date = pd.to_datetime("2021-07-04")
print(date) # Wynik: 2021-07-04 00:00:00
dateutil
Jeśli mamy daty w formacie tekstowym, możemy użyć modułu dateutil
, który automatycznie rozpoznaje różne formaty dat.
from dateutil import parser
# Parsowanie daty z tekstu
date = parser.parse("4th of July, 2021")
print(date) # Wynik: 2021-07-04 00:00:00
Czasami chcesz stworzyć listę dat, np. wszystkie dni w określonym okresie. Używamy do tego funkcji pd.date_range()
.
Funkcja pd.date_range przyjmuje datę początkową, datę końcową i opcjonalny kod częstotliwości oraz zwraca regularną sekwencję dat.
# Tworzenie zakresu dat od 1 stycznia do 7 stycznia 2023
date_range = pd.date_range('2023-01-01', '2023-01-07')
print(date_range)
Można łatwo wygenerować daty co tydzień za pomocą funkcji pd.date_range()
z argumentem freq
.
# Generowanie dat co tydzień, od 1 stycznia 2023, przez 4 tygodnie
weekly_dates = pd.date_range('2023-01-01', periods=4, freq='W')
print(weekly_dates)
W Pandas służy do tego metoda shift, która pozwala przesunąć dane w czasie o określoną liczbę wpisów. W przypadku szeregów czasowych próbkowanych z równomierną częstotliwością metoda ta pozwala na zbadanie trendów w czasie.
import pandas as pd
data = pd.DataFrame({
'sales': [300, 320, 310, 330, 340],
'date': pd.date_range(start='2023-01-01', periods=5, freq='D')
}).set_index('date')
data['previous_day_sales'] = data['sales'].shift(1)
data['sales_increase'] = data['sales'] > data['previous_day_sales']
print(data)
#Wynik
# sales previous_day_sales sales_increase
#date
#2023-01-01 300 NaN False
#2023-01-02 320 300.0 True
#2023-01-03 310 320.0 False
#2023-01-04 330 310.0 True
#2023-01-05 340 330.0 True
Obliczanie statystyk kroczących jest kolejnym rodzajem operacji specyficznych dla szeregów czasowych, które znajdziemy w Pandas. Statystyki te można obliczyć za pomocą atrybutu rolling obiektów typu Series i DataFrame. Opcja ta pozwala na tworzenie miar statystycznych, takich jak średnia krocząca, suma krocząca czy odchylenie standardowe kroczące.
Obliczanie statystyk na określonym "ruchomym" oknie danych polega na tym, że przekształcamy dane na podstawie bieżących wartości oraz wcześniejszych obserwacji z określonego przedziału (np. liczby dni, tygodni).
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Przykładowe dane czasowe (ceny akcji)
dates = pd.date_range(start='2023-01-01', periods=30, freq='D')
prices = np.random.randint(100, 200, size=len(dates))
data = pd.DataFrame({'price': prices}, index=dates)
# 7-dniowa średnia krocząca
data['7_day_mean'] = data['price'].rolling(window=7).mean()
# Wykres
plt.figure(figsize=(10, 6))
plt.plot(data.index, data['price'], label='Cena akcji')
plt.plot(data.index, data['7_day_mean'], label='7-dniowa średnia krocząca', linestyle='--')
plt.title("7-dniowa średnia krocząca cen akcji")
plt.xlabel("Data")
plt.ylabel("Cena akcji")
plt.legend()
plt.grid(True)
plt.show()
Praca ze strefami czasowymi to wyzwanie w analizie danych czasowych, zwłaszcza jeśli dane pochodzą z różnych lokalizacji. W tym celu można używać biblioteki pytz
, która umożliwia zarządzanie strefami czasowymi.
import pandas as pd
import pytz
# Dane dotyczące transakcji
data = {'transaction_time': ['2023-01-01 10:00:00', '2023-01-01 14:00:00', '2023-01-02 09:30:00'],
'city': ['New York', 'London', 'Tokyo']}
df = pd.DataFrame(data)
# Upewnienie się ze 'transaction_time' jest w formacie datetime
df['transaction_time'] = pd.to_datetime(df['transaction_time'])
# Nowa kolumna z przypisanymi strefami czasowymi
df['transaction_time'] = df['transaction_time'].dt.tz_localize('UTC') # Lokalizacja dat w UTC
# Dostosowanie stref czasowych dla odpowiednich miast
df.loc[df['city'] == 'New York', 'transaction_time'] = df.loc[df['city'] == 'New York', 'transaction_time'].dt.tz_convert('America/New_York')
df.loc[df['city'] == 'London', 'transaction_time'] = df.loc[df['city'] == 'London', 'transaction_time'].dt.tz_convert('Europe/London')
df.loc[df['city'] == 'Tokyo', 'transaction_time'] = df.loc[df['city'] == 'Tokyo', 'transaction_time'].dt.tz_convert('Asia/Tokyo')
print(df)
#Wynik
# transaction_time city
#0 2023-01-01 10:00:00+00:00 New York
#1 2023-01-01 14:00:00+00:00 London
#2 2023-01-02 09:30:00+00:00 Tokyo
datetime64
Tworzenie obiektu datetime64
jest proste – wystarczy podać datę jako łańcuch znaków i określić typ danych:
import numpy as np
# Znacznik czasu na poziomie dnia
date_day = np.datetime64('2021-07-04', 'D')
print(date_day) # Wynik: 2021-07-04
# Znacznik czasu na poziomie minut
date_minute = np.datetime64('2021-07-04 12:00', 'm')
print(date_minute) # Wynik: 2021-07-04T12:00
# Znacznik czasu na poziomie nanosekund
date_ns = np.datetime64('2021-07-04 12:59:59.50', 'ns')
print(date_ns) # Wynik: 2021-07-04T12:59:59.500000000
NumPy pozwala na wykonywanie operacji wektorowych na dużych zbiorach dat. Możemy np. dodać dni do istniejącej daty:
import numpy as np
# Tworzenie daty w formacie datetime64
date_np = np.datetime64('2024-19-10')
print(date_np) # Wynik: 2024-19-10
date_range = date_np + np.arange(12)
print(date_range)
#wynik
['2021-07-04' '2021-07-05' '2021-07-06' '2021-07-07' '2021-07-08'
'2021-07-09' '2021-07-10' '2021-07-11' '2021-07-12' '2021-07-13'
'2021-07-14' '2021-07-15']
🛑 Uwaga: Kiedy używać
datetime64
z NumPy?
- Kiedy pracujesz z dużymi zbiorami danych czasowych.
- Kiedy potrzebujesz wydajności w operacjach wektorowych na datach (np. dodawanie, odejmowanie dni).
- Kiedy wymagana jest precyzja w nanosekundach lub chcesz skorzystać z szybkich operacji na datach.
NumPy i datetime
oferują różne kody formatu, które można używać do manipulowania wyświetlaniem dat.
from datetime import datetime
# Wyświetlanie w formacie 'YYYY-MM-DD HH:MM:SS'
formatted_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(formatted_date) # Wynik 2024-10-19 15:38:34
Oprócz datetime64
, NumPy oferuje typ timedelta64
Służący do przechowywania czasów trwania lub odstępów czasu dostępny. Jest on wydajniejszym zamiennikiem natywnego typu datetime.timedelta z Pythona, bazującym na typie numpy.timedelta64.
import numpy as np
# Obliczanie różnicy między datami
date1 = np.datetime64('2023-01-01')
date2 = np.datetime64('2023-01-10')
difference = date2 - date1
print(difference) # Wynik: 9 days
Na co pozwala biblioteka Numpy?
Tworzenie tablicy z samymi zerami:
a = np.zeros((3, 4)) # 3 wiersze, 4 kolumny
Obliczanie średniej:
a = np.array([1, 2, 3, 4, 5])
mean = np.mean(a)
print(mean)
Ćwiczenia dla tego tematu zostały zebrane tutaj.
Kliknij tutaj, aby wrócić do strony głównej kursu.