Wprowadzenie do pandas (Python)

06 Jan 2020 / admin

W tym wpisie spróbuję napisać krótkie wprowadznie do modułu (biblioteki) pandas. Obiekt pandas DataFrame służy nam do prostych operacji na danych, początkowe wrażenie jest takie jak byśmy operowali na dużym arkuszu kalkulacyjnym. Róznica jest taka, że pandas potrafi dużo więcej (zobacz wpis o operacjach groupby itp.) i a operacje wykonywane są znacznie szybciej. Przed prezentacją podstaw "pandy" dodajmy, że podobne konstrukcje występują w wielu programach do obliczeń statystycznych (np. data frame albo data table w R). Przed dalszymi krokami zaimportujemy moduł komendą import pandas as pd (będziemy często odwoływać się do pandas, więc wygodnie będzie nam używać "aliasu" pd).
Utwórzmy zatem przykładowy DataFrame, złożony z 2 kolumn i 5 wierszy (co można później sprawdzić wykonując komendę df1.shape).

df1 = pd.DataFrame({"col_a": [1, 2, 3, 5, 10], "col_b": [10, 10, 20, 25, 20]})

Aby poznać podstawy, spróbujmy przeprowadzić kilka prostych operacji:

  • odwołanie do pojedynczej kolumny: df1.col_a lub df1['col_a']
  • odwołanie do kilku kolumn: df1[lista_kolumn] - np. df1[['col_a', 'col_b']]
  • odwołanie do wybranych wierszy kolumny: df1.col_a[2:4] lub df1['col_a'][2:4] (domyślnie indeksowanie tak jak w listach, czyli od zera, ale jeśli chcemy możemy zmienić indeksy)

Oczywiście na wynikach tych operacji (czyli pojedynczej kolumnie lub wycinku ramki danych) chcemy przeprowadzić obliczenia. Spójrzmy na te przykłady:

  • suma z danej kolumny: df1.col_a.sum() lub df1['col_a'].sum()(oczywiście analogicznie możemy obliczyć sumę "wycinka" - wybranych wierszy pojedynczej kolumny)
  • średnia z danej kolumny: df1.col_a.mean() lub df1['col_a'].mean()
  • podobnie możemy skorzystać z metod np.: .std() (odchylenie standardowe), .min(), .max(), .cumsum() (skumulowana suma)
  • radzenie sobie z obserwcjami - brakami danych (not a number: NaN lub np.nan): df1.dropna() () lub df1.fillna(-99) (zastąpienie NaN na podaną wartość, np. -99)
  • suma kolumn DataFrame: df1.sum(axis=0)
  • suma wierszy DataFrame: df1.sum(axis=1)

df1.head() - ogląd danych (wyświetla pierwszych kilka wierszy) df1.columns - lista kolumn c.d.n.

Operacja na zbiorach danych (w Python i R) - cz. 1

18 Aug 2018 / admin

Już pisałem, że same obliczenia zwykle zajmują 10-15% czasu. Z pozostałych 85-90% większość trzeba przezanczyć na sprawdzenie i przekształcanie danych. Dziś przestawię jak efektywnie przeszktałcać dane w Python (będzie też trochę o R). Wyobrażmy sobie, że mamy tabelę (ramkę danych) z codziennymi wydatkami, np.:

KATEGORIA CENA ILOSC WART
Żywność 1,5 2 3
Rozrywka 24 1 24
Żywność 4 5 20
Ubrania 99 1 99
Ubrania 25 2 50
Żywność 3 1 3
Żywność 0,5 40 20
Rozrywka 7,5 3 22,5
Żywność 14,99 3 44,97
Rozrywka 50 1 50


Naturalnym problemem analitycznym jest policzenie sumy wydaktów dla każdej kategorii. Wydawać się może, że osiągniemy to przy pomocy pętli, coś w rodzaju:

  • Weź zmienną SUMA = 0
  • Kolejno dla wierszy i = 1,...,N (gdzie N to liczba wierszy) wykonaj polecenia:
    • Sprawdź czy kolumna KATEGORIA == "Żywność"
    • Jeśli powyższy warunek jest prawdziwy to dodaj do zmiennej SUMA wartość kolumny WART


Następnie to samo to dla kategorii "Ubrania" i "Rozrywka". Takie rozwiązanie zadziała i otrzymany prawidłowy wyniki (90,97), ale można lepiej (bardziej zwięzły zapis i znacznie krótszy czas niezbędny do obliczenia). Takie operacje na danych to standardowa operacja agregująca ("GROUP BY" w SQL), standardowo zaimplementowana w bazach danych np. SQL, ale także w Python (Pandas) i R (data.table albo dplyr). W takiej operacji podajemy zmienną grupującą (czyli zmienną, która rozróżnia podgrupy, tu: KATEGORIA) i operacje jakie chcemy wykonać w każdej z podgrup (tu: suma zmiennej WART). Oczywiście potencjalny wachlarz zastosować to nie tylko suma, równie często korzystamy ze średniej i liczby wystąpień ("COUNT" w SQL) albo liczby unikalnych wartości danej zmiennej ("COUNT DISTINCT").

Przykład z życia wzięty.

W bazie danych z niewiadonych przyczyn "pojawiły się" braki obseracji. Skonstruowałem indykator (zmienną zerojedynkową) dla braku danych i okazało się, że udział braków danych sięga ok. 40%. Przyjrzyjmy się temu bliżej - policzyłem udział braków danych wg miejscowości, wyniki są takie:

Zgierz 0
Łódź 1
Ostrołęka 1
Warszawa 0
Radomsko 0
Pabianice 0
Piotrków Tryb. 1
Tomaszów Maz. 1
Kalisz 0


Widzicie to co ja? Braki obserwacji są tylko dla tych miejscowości, które mają "polskie litery". To pokazało, gdzie tkwi problem - różne kodowanie polskich znaków w różnych plikach (baza powstawała poprzez łączenie różnych zbiorów danych). Teraz rozwiązanie problemu zajęło mniej niż 5 minut.

Przykładowe kody (implementacja w Pandas + Python i Data.table + R)

Okazuje się, że implementacja przedstawionych wyżej operacji jest bardzo prosta i przyjemna, zarówno w Python jak i R. Przy okazji tych przykładów podaję odpowiedniki komend dla zapytań SQL -- przyda się tym, którzy znają choćby podstawy SQL albo gdy chcecie wyjaśnić sens jakieś operacji "czystemu" programiście.
Poniżej kody, przy założeniu że mamy w pamięci ramkę danych o nazwie DF, zawierającą zmienne Kategoria i Wartosc.

Operacje group by w Python - Pandas import pandas as pd
# wprowadz ramke danych, np. DF = pd.DataFrame( {"Wart": [0,1,3,3,4,5,6,6,8,8], "Kategoria": [1,1,1,1,2,2,2,2,2,2]} )
DF.groupby(by = "Kategoria").sum()
DF.groupby(by = "Kategoria").count()
DF.groupby(by = "Kategoria").unique()
DF.groupby(by = "Kategoria").nunique()
# Trochę bardziej elegancko
DF_GroupBy = DF.groupby(by = "Kategoria")
DF_GroupBy.sum()
DF_GroupBy.count()    # itd.


Operacje group by w R - data.table library(data.table)
# wprowadz ramke danych, np. DF = data.frame( Wart = c(0,1,3,3,4,5,6,6,8,8), Kategoria = c(1,1,1,1,2,2,2,2,2,2) )
DF = data.table(DF)
DF[ , .(Suma = sum(Wart)), by = Kategoria]
DF[ , .N, by = Kategoria]
DF[ , .(Unikalne = unique(Wart)), by = Kategoria]
DF[ , .(L_Unikalnych = length(unique(Wart))), b = Kategoria]

Przydatne drobiazgi (nie tylko do nauki)

13 Mar 2018 / admin

Życie składa się z drobiazgów, a niektóre drobiazgi ułatwiają życie. Dotyczy to nauki data science, a także w trakcie pracy "na serio". O jakich drobiazgach dziś opowiem?

  • Dobre IDE. IDE (integrated development environment) jest łącznikiem pomiędzy interpreterem (w przypadku Py i R) a użytkownikiem. Zawiera dobry edytor, który ładnie podświetla składnię. Mój ulubiony PyCharm podpowiada mi jak poprawić czytelność kodu, kontroluje indentację w kodzie (wiadomo jakie to ma znaczenie w Py!) i pokazuje jakie obiekty mam w pamięci. Do R polecam RStudio, ale uczciwie mówię -- nie próbowałem innych.
  • Cheat sheets. Ściągawki są dobre nie tylko na egzaminach ;) Takie ściągawki są fajne jako podręczny reference do kodu. Wiadomo, czasem zapomnimy, czasem potrzebujemy zrobić coś innego niż zwykle. Te z DataCamp są ok, ale w sieci jest wiele, każdy ma nieco inne potrzeby i gust, ale naprawdę można wybierać. Jeśli chcecie mieć jedną kartkę to do R używałem ofertowanej przez RStudio (tu). Ściagawki drukuję w kolorze na grubszym papierze (150 g). Można też wydrukować w formacie A3 i zawiesić jako plakat na ścianie.
  • Notepad++. Oczywiście do naszego kodu najlepiej używać edytora w naszym ulubionym IDE. Jeśli trzeba podejrzeć duży plik .txt czy .csv - lepiej użyć jakiegoś dobrego edytora czystego tekstu (nie mylić z Wordem itp.). Notepad++ przydaje się kiedy musimy skorzystać z kodu napisanego w innym języku, np. dodajemy zapytania SQL albo przepisujemy kod Java do naszego ulubionego Py lub R. Oczywiscie N++ jest bezpłatny.

Jeśli znacie jakiś inny drobiazg, który ułatwia pracę (ale nie mówimy o ekpresie do kawy :) to proszę o maila, zamieszczę update cytując autora ciekawej propozycji.



1 2 3 następny ... koniec