Czego nauczyłem się pracując z pandas



Autor

Paweł Romanowski - http://github.com/pawroman


http://daftcode.pl

Agenda


  • Czym jest pandas?
  • Zastosowania, funkcjonalność
  • Przykłady
  • Moje doświadczenia i wskazówki

Czym jest pandas?


  • Tabelaryczne struktury danych + operacje na nich
  • Wygodna manipulacja danymi
  • Dobre wsparcie dla "timeseries" i danych typu N/A
  • Wydajność
  • Używa NumPy, część stacku SciPy (NumPy, SciPy, matplotlib, SymPy, IPython)
  • "(...) it has the broader goal of becoming the most powerful and flexible open source data analysis / manipulation tool available in any language. It is already well on its way toward this goal."

Zastosowania


  • Analiza, eksploracja danych
  • Pre-processing, filtrowanie, oczyszczanie danych
  • Obliczenia statystyczne, agregacja
  • Raportowanie, wykresy
  • (W moim przypadku) analiza i grupowanie danych z/do MongoDB
In [1]:
posts_data = [
    {"id": 1, "ts": "2014-01-01T10:00", "name": "Zbychu",
     "message": "hello world", "likes": 16},

    {"id": 2, "ts": "2014-01-01T13:37", "name": "Zbychu",
     "likes": 20},

    {"id": 3, "ts": "2014-01-01T15:35", "name": "biedny student",
     "message": "pandas 3 bardzo proszę pls", "likes": 3},

    {"id": 4, "ts": "2014-01-02T19:42", "name": "julius_caesar",
     "message": "veni, vidi, vici", "likes": 22},

    {"id": 5, "ts": "2014-02-04T12:02", "name": "julius_caesar",
     "message": "coś po łacinie", "likes": 10},

    {"id": 6, "ts": "2014-04-15T23:15", "name": "kotek",
     "message": "miau miau miau bardzo miau", "likes": 5},

    {"id": 7, "ts": "2014-04-15T18:30", "name": "Zbychu",
     "message": "hello pandas hello hello", "likes": 7},
]

Ładowanie danych


In [2]:
import pandas

posts = pandas.DataFrame(posts_data)
posts
Out[2]:
id likes message name ts
0 1 16 hello world Zbychu 2014-01-01T10:00
1 2 20 NaN Zbychu 2014-01-01T13:37
2 3 3 pandas 3 bardzo proszę pls biedny student 2014-01-01T15:35
3 4 22 veni, vidi, vici julius_caesar 2014-01-02T19:42
4 5 10 coś po łacinie julius_caesar 2014-02-04T12:02
5 6 5 miau miau miau bardzo miau kotek 2014-04-15T23:15
6 7 7 hello pandas hello hello Zbychu 2014-04-15T18:30

7 rows × 5 columns

Sortowanie, wypełnianie N/A


In [3]:
posts = posts.sort("likes", ascending=False).fillna("[ No Comment ]")
posts
Out[3]:
id likes message name ts
3 4 22 veni, vidi, vici julius_caesar 2014-01-02T19:42
1 2 20 [ No Comment ] Zbychu 2014-01-01T13:37
0 1 16 hello world Zbychu 2014-01-01T10:00
4 5 10 coś po łacinie julius_caesar 2014-02-04T12:02
6 7 7 hello pandas hello hello Zbychu 2014-04-15T18:30
5 6 5 miau miau miau bardzo miau kotek 2014-04-15T23:15
2 3 3 pandas 3 bardzo proszę pls biedny student 2014-01-01T15:35

7 rows × 5 columns

Selekcja, przypisanie


In [4]:
posts.loc[posts.likes >= 10, "message"] = posts["message"].str.decode("utf8").str.upper()
posts
Out[4]:
id likes message name ts
3 4 22 VENI, VIDI, VICI julius_caesar 2014-01-02T19:42
1 2 20 [ NO COMMENT ] Zbychu 2014-01-01T13:37
0 1 16 HELLO WORLD Zbychu 2014-01-01T10:00
4 5 10 COŚ PO ŁACINIE julius_caesar 2014-02-04T12:02
6 7 7 hello pandas hello hello Zbychu 2014-04-15T18:30
5 6 5 miau miau miau bardzo miau kotek 2014-04-15T23:15
2 3 3 pandas 3 bardzo proszę pls biedny student 2014-01-01T15:35

7 rows × 5 columns

Index


In [5]:
posts_id = posts.set_index("id")
posts_id.sort_index().ix[3:6]
Out[5]:
likes message name ts
id
3 3 pandas 3 bardzo proszę pls biedny student 2014-01-01T15:35
4 22 VENI, VIDI, VICI julius_caesar 2014-01-02T19:42
5 10 COŚ PO ŁACINIE julius_caesar 2014-02-04T12:02
6 5 miau miau miau bardzo miau kotek 2014-04-15T23:15

4 rows × 4 columns

Datetime index


In [6]:
posts_ts = posts.set_index("ts").sort_index()
posts_ts.index = posts_ts.index.to_datetime()
In [7]:
posts_ts.ix["2014-01-01 12:00":"2014-01-01T16:00"]
Out[7]:
id likes message name
2014-01-01 13:37:00 2 20 [ NO COMMENT ] Zbychu
2014-01-01 15:35:00 3 3 pandas 3 bardzo proszę pls biedny student

2 rows × 4 columns

Strefy czasowe


In [8]:
posts_warsaw = posts_ts.tz_localize("UTC").tz_convert("Europe/Warsaw")
posts_warsaw
Out[8]:
id likes message name
2014-01-01 11:00:00+01:00 1 16 HELLO WORLD Zbychu
2014-01-01 14:37:00+01:00 2 20 [ NO COMMENT ] Zbychu
2014-01-01 16:35:00+01:00 3 3 pandas 3 bardzo proszę pls biedny student
2014-01-02 20:42:00+01:00 4 22 VENI, VIDI, VICI julius_caesar
2014-02-04 13:02:00+01:00 5 10 COŚ PO ŁACINIE julius_caesar
2014-04-15 20:30:00+02:00 7 7 hello pandas hello hello Zbychu
2014-04-16 01:15:00+02:00 6 5 miau miau miau bardzo miau kotek

7 rows × 4 columns

Resample


In [9]:
posts_by_day = posts_ts.resample("D", how="sum").dropna()
posts_by_day
Out[9]:
id likes
2014-01-01 6 39
2014-01-02 4 22
2014-02-04 5 10
2014-04-15 13 12

4 rows × 2 columns

Reshaping


In [10]:
by_month = posts_ts.pivot_table(
    "likes", cols="name", rows=posts_ts.index
).resample("M", how="sum").sort_index(ascending=False)

by_month
Out[10]:
name Zbychu biedny student julius_caesar kotek
2014-04-30 7 NaN NaN 5
2014-03-31 NaN NaN NaN NaN
2014-02-28 NaN NaN 10 NaN
2014-01-31 36 3 22 NaN

4 rows × 4 columns

Wykresy


In [11]:
%matplotlib inline

plots = by_month.plot(kind="bar", figsize=(10, 6), title="Likes per month per user")

To dopiero początek!


  • Zapis/odczyt: CSV, excel, HTML, JSON, SQL, HDF5, pickle, ...
  • Merge/join/groupby a'la SQL
  • Funkcje statystyczne, numeryczne, interpolacja
  • Dane typu "sparse"
  • Ekosystem SciPy
  • ...

Moje wnioski (1)


  • pandas everywhere!!!!11
  • Nigdy więcej "ręcznej" obróbki danych
In [12]:
import csv

def the_manual_way():
    with open("data.csv") as f:
        reader = csv.reader(f)
        data = []

        for row in reader:
            data.append({"ts": parse(row[0]), "name": row[1]})
            print "I wish I've known pandas"
    # ... furious data wrangling ...        
In [13]:
import pandas

def the_pandas_way():
    data = pandas.read_csv("data.csv")

    # use pandas, Luke!
    data.set_index("ts").sort_index()["2014-01-01":].groupby("name")["likes"].sum()

Moje wnioski (2)


  • pandas nie rozwiązuje wszystkich problemów
  • Spora funkcjonalność
  • Użyć jej dla wydajności - unikać "pure Python"
  • API: unikać przeliczania "online", OK dla pre-agregacji
  • Lepiej pracuje się z "gotowymi" danymi
  • Spójny model danych

Referencje


Przydatne linki, tutoriale

Linki


Prezentacja dostępna pod adresem: http://pawroman.github.io/pywaw-pandas/

Wpisy na blogu: http://piesnakod.pl/tag/pandas/

Kod prezentacji: https://github.com/pawroman/pywaw-pandas


Wykonano w IPython notebook http://ipython.org/notebook

Dziękuję



Paweł Romanowski - http://github.com/pawroman


Szukamy Python'owców!

http://daftcode.pl/python_dev