Pandasことはじめ
Jupyter NotebookやColabで頻出するスニペットまとめ。
準備
Notebookの先頭でimportしておく。NumPyは必須ではないが型の指定で使うことがある。
import pandas as pd
pd.options.display.max_columns = None # カラムの数
pd.options.display.max_rows = 100 # 行の数
pd.options.display.max_colwidth = 300 # カラムの横幅
import numpy as np
Notebookの構成
Notebookでは変数空間が共有されるため、コードブロックは基本的に直前の結果となるDataFrameだけに依存し、副作用を起こさないよう冪等に書くことが望ましい。そうすることで変更したコード以降を再実行すれば必ず結果が更新される。各ブロックは以下のように構成して、例えばdfaからdfzまで使うなどを自分のルールにしておくと良い。
# 前のブロックの結果がdfa
dfb = dfa.copy()
dfb = ...
…
# このブロックの結果はdfb
データの取り込み
BigQueryのデータを扱う
ColabではGoogle認証をしてIPython Magicsを使うのがおすすめ。Pandasのread_gbqは使わない。
%load_ext google.cloud.bigquery
from google.colab import auth
auth.authenticate_user()
from google.cloud.bigquery import magics
認証した上で、コードブロックに
%%bigquery df --project <your-gcp-project>
SELECT
...
FROM
...
のようにクエリを書いて実行すると df で参照できる。データ転送が遅い場合はStorage APIを有効にするかClient APIを使うと改善される場合がある。
PythonのデータをDataFrameにする
元のデータ型によってDataFrame()とDataFrame.from_dict()とDataFrame.from_records()を使い分ける。合わないときはPythonのmap()かリスト内包で変換する。
ex = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}]
pd.DataFrame(ex)
# a b
# 0 1 2
# 1 3 4
Indexを設定する
indexによって集計などの動作が変わるので、DataFrame.reset_index()とDataFrame.set_index()はこまめに行う。
ex = [{'a': 1, 'b': 2}, {'a': 1, 'b': 3}, {'a': 2, 'b': 4}]
df = pd.DataFrame(ex).set_index('a')
df
# b
# a
# 1 2
# 1 3
# 2 4
df.reset_index()
# a b
# 0 1 2
# 1 1 3
# 2 2 4
結合
DataFrame.join()またはDataFrame.merge()を使う。
dfn = pd.DataFrame({'id': ['a', 'b', 'c', 'd'], 'name': ['apple', 'banana', 'cacao', 'durian']}).set_index('id')
dfp = pd.DataFrame({'id': ['a', 'a', 'b', 'c', 'e'], 'price': [100, 90, 150, 200, 500]}).set_index('id')
dfn.join(dfp)
# name price
# id
# a apple 100.0
# a apple 90.0
# b banana 150.0
# c cacao 200.0
# d durian NaN
集計
グループ化
GroupBy.agg()を使う。
ex = [{'name': 'foo', 'value': 1}, {'name': 'bar', 'value': 2}, {'name': 'foo', 'value': 3}, {'name': 'bar', 'value': 4}]
df = pd.DataFrame(ex)
df.groupby('name').agg(tuple)
# value
# name
# bar (2, 4)
# foo (1, 3)
グループの要素数
GroupBy.size()を使う。結果はSeriesになる。
ex = [{'name': 'foo', 'value': 1}, {'name': 'bar', 'value': 2}, {'name': 'foo', 'value': 3}]
df = pd.DataFrame(ex)
df.groupby(['name']).size().rename('size').to_frame()
# size
# name
# bar 1
# foo 2
グループの展開
DataFrame.explode()で指定したカラムのコレクションが展開される
df = pd.DataFrame([{'a': 1, 'b': [2, 3]}, {'a': 2, 'b': [4, 5]}])
df.explode('b')
# a b
# 0 1 2
# 0 1 3
# 1 2 4
# 1 2 5
カラムの操作
削除
DataFrame.drop()を使う。
df.drop('hoge', axis=1)
# もしくは
df.drop(columns=['hoge'])
行の操作
重複排除
DataFrame.drop_duplicates()で値の重複を排除する。値だけであることに注意。
df = pd.DataFrame([{'a': 1, 'b': 2}, {'a': 1, 'b': 2}, {'a': 2, 'b': 2}, {'a': 2, 'b': 2}])
df.drop_duplicates()
# a b
# 0 1 2
# 2 2 2
df.set_index('a').drop_duplicates()
# b
# a
# 1 2
行番号で抽出
df.iloc[1:10]
値でフィルタ
df = pd.DataFrame([{'col': 'foo'}, {'col': 'bar'}, {'col': 'hoge'}])
# OK
df[df['col'].str.len() > 3]
# OK
df[df['col'].map(len) > 3]
# NG
df[len(df['col']) > 3]
df[]の中身はベクトルでなくてはならないことに注意。
DataFrameの行でループ
for index, row in df.iterrows():
print(row['col'])
可視化
matplotlib - 時系列データならこれ
graphviz - グラフ描画。pygraphvizではなくgraphvizがおすすめ
seaborn - heatmapとclustermap