10 przydatnych komend Pandas
Niektóre komendy może już znasz, ale nie raczej nie wiedziałeś, że mogą być używane w ten sposób. Pandas to pakiet Pythona powszechnie używany do pracy z danymi ustrukturyzowanymi. W internecie znajdziesz wiele dobrych samouczków na jego temat, jednak dziś chciałbym przedstawić Ci kilka fajnych sztuczek, których mogłeś wcześniej nie znać, a są całkiem przydatne.
read_csv
Wszyscy zapewne znają to polecenie. Ale jeśli danych, które próbujesz odczytać, jest wiele, spróbuj dodać argument: nrows = 5
, aby przeczytać tylko niewielką część tabeli, zanim faktycznie załadujesz jej całość. W ten sposób możesz uniknąć błędów, polegających na wyborze złego separatora (nie zawsze może być on oddzielony przecinkami).
(lub, możesz też użyć polecenia head
w linuxie, aby sprawdzić pierwsze 5 wierszy (mniej więcej) w dowolnym pliku tekstowym: head -n 5 data.txt
.
W ten sposób możesz wyodrębnić listę kolumn, używając df.columns.tolist()
, aby wyodrębnić wszystkie kolumny, a następnie dodać argument usecols = ['c1', 'c2',…]
, aby załadować tylko potrzebne kolumny. Ponadto, jeśli znasz typy danych kilku konkretnych kolumn, możesz dodać argument dtype = {'c1': str, 'c2': int,…}
, aby ładowały się szybciej. Kolejną zaletą tego argumentu jest to, że jeśli masz kolumnę zawierającą zarówno łańcuchy znaków, jak i liczby, dobrą praktyką jest zadeklarowanie jej typu jako stringa, dzięki czemu nie wystąpią błędy podczas próby łączenia tabel przy użyciu tej kolumny jako klucza.
select_dtypes
Jeśli już musisz wykonać przetwarzanie danych w Pythonie, to to polecenie zaoszczędzi Ci trochę czasu. Po odczytaniu tabeli domyślnymi typami danych dla każdej kolumny mogą być bool, int64, float64, object, category, timedelta64 lub datetime64. Możesz najpierw sprawdzić dystrybucję przez:
df.dtypes.value_counts()
aby poznać wszystkie możliwe typy danych w ramce, a następnie wykonać:
df.select_dtypes(include=['float64', 'int64'])
aby wybrać ramkę danych tylko z funkcjami numerycznymi.
copy
To dość ważne polecenie, jeśli jeszcze o nim nie słyszałeś. Jeśli wykonasz następujące polecenia:
import pandas as pd
df1 = pd.DataFrame({ 'a':[0,0,0], 'b': [1,1,1]})
df2 = df1
df2['a'] = df2['a'] + 1
df1.head()
Okaże się, że df1 zostało zmienione. Dzieje się tak, ponieważ df2 = df1 nie tworzy kopii df1 i nie przypisuje jej do df2, ale ustawia wskaźnik wskazujący na df1. Wszelkie zmiany w df2 spowodują zmiany w df1. Aby to naprawić, możesz wykonać:
df2 = df1.copy()
lub:
from copy import deepcopy
df2 = deepcopy(df1)
map
To fajne polecenie do łatwej transformacji danych. Najpierw definiujesz słownik, gdzie „klucze”, to stare wartości, a „wartości” to nowe wartości.
level_map = {1: 'high', 2: 'medium', 3: 'low'}
df['c_level'] = df['c'].map(level_map)
Kilka przykładów: True, False to 1, 0 (do modelowania); definiowanie poziomów; zdefiniowane przez użytkownika kodowanie leksykalne.
apply czy nie apply?
Gdybyśmy chcieli utworzyć nową kolumnę z kilkoma innymi kolumnami jako wejściami, funkcja apply bywa czasem bardzo przydatna.
def rule(x, y):
if x == 'high' and y > 10:
return 1
else:
return 0
df = pd.DataFrame({ 'c1':[ 'high' ,'high', 'low', 'low'], 'c2': [0, 23, 17, 4]})
df['new'] = df.apply(lambda x: rule(x['c1'], x['c2']), axis = 1)
df.head()
W powyższych kodach definiujemy funkcję z dwiema zmiennymi wejściowymi i używamy funkcji apply, aby zastosować ją do kolumn „c1” i „c2”.
Ale problem funkcji apply
polega na tym, że czasami jest ona zbyt wolna. Powiedzmy, że chcesz obliczyć maksymalnie dwie kolumny „c1” i „c2”, oczywiście możesz to zrobić:
df['maximum'] = df.apply(lambda x: max(x['c1'], x['c2']), axis = 1)
ale znajdziesz wynik znacznie wolniej niż używając tego polecenia:
df['maximum'] = df[['c1','c2']].max(axis =1)
Wniosek: Nie używaj apply, jeśli możesz wykonać tę samą pracę z innymi wbudowanymi funkcjami (często są szybsze). Na przykład, jeśli chcesz zaokrąglić kolumnę „c” do liczb całkowitych, wykonaj round(df['c'], 0)
lub df['c'].round(0)
, zamiast używać funkcji: df.apply(lambda x: round(x['c'], 0), axis = 1)
.
Liczniki wartości
Jest to polecenie do sprawdzania dystrybucji wartości. Na przykład, jeśli chcesz sprawdzić, jakie są możliwe wartości i częstotliwość dla każdej indywidualnej wartości w kolumnie „c”, możesz użyć:
df['c'].value_counts()
Znajdziemy tu też parę przydatnych sztuczek/argumentów :
- normalize = True: jeśli chcesz sprawdzić częstotliwość zamiast ilości.
- dropna = False: jeśli chcesz również uwzględnić brakujące wartości w stats.
df['c'].value_counts().reset_index()
: jeśli chcesz przekonwertować tabelę statsów na dataframe Pandasa i manipulować nią.df['c'].value_counts().reset_index().sort_values(by='index')
: pokazuje statystyki posortowane według odrębnych wartości w kolumnie „c” zamiast ilości.
Liczba brakujących wartości
Podczas budowania modeli możesz chcieć wykluczyć wiersz ze zbyt wieloma brakującymi wartościami lub kilka wierszy ze wszystkimi brakującymi wartościami. Możesz użyć .isnull ()
i .sum ()
, aby policzyć liczbę brakujących wartości w określonych kolumnach.
import pandas as pd
import numpy as np
df = pd.DataFrame({ 'id': [1,2,3], 'c1':[0,0,np.nan], 'c2': [np.nan,1,1]})
df = df[['id', 'c1', 'c2']]
df['num_nulls'] = df[['c1', 'c2']].isnull().sum(axis=1)
df.head()
Wybierz wiersze z określonymi identyfikatorami
W SQL możemy to zrobić za pomocą SELECT * FROM… WHERE ID in ("A001", "C022",…)
, aby uzyskać wpisy z określonymi identyfikatorami. Jeśli chcesz zrobić to samo w pandas, możesz użyć:
df_filter = df['ID'].isin(['A001','C022',...])
df[df_filter]
Percentyle
Masz kolumnę liczbową i chcesz sklasyfikować wartości w tej kolumnie w grupy, powiedzmy najwyższe 5% w grupie 1, 5–20% w grupie 2, 20%-50% w grupie 3, 50% w grupie 4. Oczywiście, możesz to zrobić za pomocą pandas.cut, ale chciałbym zaproponować inne rozwiązanie:
import numpy as np
cut_points = [np.percentile(df['c'], i) for i in [50, 80, 95]]
df['group'] = 1
for i in range(3):
df['group'] = df['group'] + (df['c'] < cut_points[i])
# or <= cut_points[i]
które to uruchamia się znacznie szybciej (gdyż nie używa funkcji apply).
to_csv
Znowu, to polecenie, z którego wszyscy korzystają. Chciałbym jednak wskazać dwie sztuczki. Pierwsza z nich to:
print(df[:5].to_csv())
Możesz użyć tego polecenia, aby wydrukować pierwsze pięć wierszy dokładnie tego, co zostanie zapisane w pliku.
Inną sztuczką jest łączenie liczb całkowitych i brakujących wartości. Jeśli kolumna zawiera zarówno brakujące wartości, jak i liczby całkowite, typ danych nadal będzie floatem, a nie int. Kiedy eksportujesz tabelę, możesz dodać float_format='%.0f'
, aby zaokrąglić wszystkie float do liczb całkowitych. Użyj tej sztuczki, jeśli chcesz otrzymać tylko liczby całkowite na wyjściu dla wszystkich kolumn - pozbędziesz się wszystkich denerwujących '.0'.
Oryginał artykułu w języku angielskim możesz przeczytać tutaj.