学習方法¶
Pandas の初期段階での学習方法について思いつくままに記す。なお、コンソールは基本的には IPython を利用する前提だ。プロットなどでは Jupyter Notebook を利用するのが自然かも知れない。
IPython のプロファイルを仕込む¶
Pandas を学習するときには次のコードを毎回コンソールに打ち込むことになる:
import pandas as pd
import numpy as np
この手間を省略するために、IPython のプロファイル機能を活用する。
bash$ PANDAS_PROFILE_NAME=pandas
bash$ ipython profile create $PANDAS_PROFILE_NAME
bash$ cd $(ipython locate profile $PANDAS_PROFILE_NAME)/startup
bash$ cat common_import.py <<EOF
import pandas as pd
import numpy as np
EOF
他にも、ダミー DataFrame オブジェクトを生成するコードを置くのもよいだろう。
そして IPython セッションを開始するときには次のようにするのだ:
bash$ ipython --profile $PANDAS_PROFILE_NAME
基本ドキュメントを精読する¶
初学者は Pandas 公式文書の次の二点にまず目を通すことになる。ここに書かれているコードを可能な限り IPython などで試すことで Pandas の本質的な機能を体得することになる。
Getting Started の Getting started tutorials
User Guide の 10 minutes to pandas
Getting started tutorials ノート¶
このチュートリアルを実施する際にデモ CSV ファイルが必要だ。普通に読んでいればいずれのファイルもダウンロードできるので問題ないが、オフラインで作業するときにはあらかじめダウンロードしておく。
CSV ファイルから DataFrame
オブジェクトを生成するコードを上述のスクリプトに含めておくといい。
titanic = pd.read_csv("path/to/titanic.csv")
air_quality_short = pd.read_csv("path/to/air_quality_no2.csv", index_col=0, parse_dates=True)
air_quality_long = pd.read_csv("/path/to/air_quality_no2_long.csv", parse_dates=True)
要点が各章の終わりにまとめられているので、内容を習得したか確認する。
基礎的概念
Pandas のパッケージ要素を利用するには
import pandas as pd
とする(別名定義はタイプ量節約のため)。クラス
DataFrame
は二次元の表を表す。これが当ライブラリーの主役のようなものだ。このオブジェクトの生成方法はいろいろある。ここでは
dict
オブジェクトから直接生成している。
DataFrame
の列のそれぞれはSeries
というものだ。DataFrame
オブジェクトに対して角括弧[]
を作用させるとSeries
オブジェクトとして列を参照する。
Pandas プログラミングでは
DataFrame
またはSeries
に対してメソッドを呼び出すことで何かをする。ここでの例は
.max()
と.describe()
にとどめてある。
I/O について
read_
から始まる名前の関数がファイルからの入力機能だ(アンダースコアのあとにファイルフォーマットを表す名前が付く)。GitHub のリポジトリーから
titanic.csv
をダウンロードして関数read_csv()
を必ず試すこと。ロード系関数を呼び出した後は、生成された
DataFrame
オブジェクトの内容を必ず確認すること。
反対に
.to_
から始まる名前のメソッドがファイル出力機能だ。メソッド
.to_excel()
を必ず試すこと。それから関数read_excel()
が動くことを確認すること。これらは MS Excel 形式のファイルを処理するサードパーティー製ライブラリーが何かしらインストール済みでないと動作しないだろう。
オブジェクトをチェックするのにメソッド
.head()
,.tail()
,.info()
とプロパティー.dtypes
が手軽に使える。プロパティー
.dtypes
を参照すると各列の型を確認できる。object
とあるのは実際は文字列型だと思っていいようだ。メソッド
.info()
がメモリー使用状況も出力していることに注意。
DataFrame
の部分集合へのアクセス角括弧を用いるのが基本的だ。
与えられた
DataFrame
の任意の列を抽出する方法を習得すること。列の個数にも注意。興味深いことに、角括弧に与えるキーとしてlist
は許されるがtuple
は許されない。プロパティー
.shape
でDataFrame
やSeries
の寸法が得られる。
そのような角括弧の内側には、単一の行または列ラベル、行または列ラベルのリスト、ラベルのスライス、条件付き式、またはコロンが入る。
例えばタイタニックデータに対して「35 歳を超える乗客の一覧」を抽出できるようにする。
Series.isin()
について頭の片隅に入れておく。
メソッド
.loc[]
では行名または列名を用いる。「35 歳以上の乗客の名前の一覧」を得るのに単なる角括弧では不十分である理由を理解する。
メソッド
.iloc[]
では表における添字を用いる。.loc[]
にせよ.iloc[]
にせよ、値を代入するのにも用いられる。
プロットするには
Series
とDataFrames
の両方にプロパティー.plot
が提供されていて、そこからプロット用メソッド各種を呼び出すことができるようになっている。WSL 環境で学習していて Matplotlib をインポートすると Could not connect to any X display のようなエラーメッセージが出る場合には、いったんセッションを閉じる。それから VcXsrv などの XLaunch を起動しておき、再びコンソールを開く。それから IPython を実行し直す。
IPython でやるのをいったん止めて VS Code の Jupyter Notebook Extension を利用するのも楽だ。
.ipynb
ファイルを作成するように VS Code を開くといい。bash$ code pandas-plot.ipynb
こちらでプロファイルが使えたら環境を乗り換えるのもいいか。
.plot()
でもプロットできる。上述の環境で画面が出ないときには明示的に
plt.show()
を呼び出す。メンバーデータ
.plot
に対してdir()
を呼び出すとプロットメソッド一覧を得ることを憶えておくといい。アンダースコアから始まらないものが該当する。area
bar
barh
box
density
hexbin
hist
kde
line
pie
scatter
IPython 環境ではタブ補完を利用するのも手軽でよい。
基本的には、各列は異なる要素としてプロットされる。
特定の列だけプロットすることもできる。メソッド
.plot()
がSeries
にもあることに注意する。
Pandas が生成するあらゆるプロットは Matplotlib オブジェクトだ。生成したいプロットをカスタマイズするのに Matplotlib プログラミングの技法を活用できる。
既存の列から新しい列を作成するには
代入による。左辺は
df[new_column_name] = ...
のような形であり、右辺は何らかの出力だろう。このデモコードのような処理をいくつも実行すると、欠損値の振る舞いを肌感覚で理解できる。
操作は要素ごとになされる。行をループする必要はない。
行名または列名を変えるには
rename()
を使う。キーワード引数
columns
の値はdict
か関数ということか。
統計概要を計算するには
集約系の統計は列全体または行全体について計算ができる。
基本的には欠損値は除外して計算される。
.mean()
や.median()
などの出来合いの統計メソッドで事足りるならそうする。.describe()
をもっと細かく指定するならば.agg()
を検討する。
.groupby()
は「分割・適用・結合」パターンの原動力だ。必要ならデータセットの部分集合を選択し、列名などで
.groupby()
する。そのあとに統計メソッドを適用すると、指定した列の要素別にグループ分けされて、そのグループごとに集計される。Pandas は「適用・結合」を一括して処理する。
複数列による
.groupby()
の方法を習得すること。
.value_counts()
は各列に対して、存在する値それぞれがいくつ含まれるかを勘定するのに具合が良い。SQL で言う
SELECT column_name, COUNT(1) FROM table_name GROUPBY column_name
に相当する。
表の配置を変えるには
.sort_values()
は列を整列する。一つでも複数でも整列できる。基準となる列を指定するにはキーワード引数
by
に列名または列名のリストを与える。昇順・降順を指定するにはキーワード引数
ascending
に真偽値を与える。
.sort_index()
も実装されている。
冷静に考えるとここの
.groupby()
の挙動がよくわからない。
.pivot()
は純粋にデータを再構築する一方、.pivot_table()
は集約を行う。反対に、こちらの
.pivot()
はわかりやすい。.pivot()
の結果を即.plot()
できる。この例では変動が激しすぎて何も観察できないとは思うが。.pivot_table()
のキーワード引数aggfunc
に注意。.pivot_table()
のキーワード引数margins
にTrue
を与えるとAll
という要約列が生じる。
.pivot()
の逆は.melt()
だ。「縦長を横長にする操作の逆は、横長を縦長にする」と覚える。.reset_index()
で序数によるインデックス列が新たに生成される。.melt()
によって列名がインデックス側に移動したように見える。.melt()
にキーワード引数各種を指定することで詳細にカスタマイズできる。
複数の表からデータを結合するには
関数
concat()
を使うと複数の表を、列ごとにでも行ごとにでも結合することができる。axis=0
を指定すると表を縦に結合する。Pandas では使えるところではaxis=0
とaxis=1
を指定するのでこの例で習得する。複数の表をこのように結合すると、一般的には元のデータの行を特定できなくなる。それを解決するのにキーワード引数
keys
を指定する。この例ではよくわからないが、階層のあるインデックス列が追加的に生じる。
表に対するデータベースにおける merging/joining 操作には関数
merge()
を使う。最初の
merge()
は SQL で言う LEFT INNER JOIN に相当する。キーワード引数how
とon
に注意。列名が異なる場合にはleft_on
とright_on
をon
の代わりに用いる。Pandas は当然 INNER JOIN も OUTER JOIN も提供している。
時系列データを操作するには
関数
to_datetime()
を使えば、まともな日付文字列を日付時間オブジェクトに変換することができる。最初のデモでは変換の前後で
.dtypes
をチェックするといい。以前のデモで見たように、ファイルから読み込むときにキーワード引数
parse_dates
で変換したい列を(リストで)指定するのがいい。Timestamp
オブジェクトはいろいろと有用であるので、可能な限り変換しておきたい。
Pandas の日付時間オブジェクトには時間計算、論理演算、日付に関連するプロパティー
.dt
が備わっている。月を抽出するデモでは、
.dt.month
から得られる列の要素型がint
であることに注意。各曜日の各所における二酸化窒素の例での
.groupby()
は難しい。プロットの例では、ラベルを設定する処理を
.plot()
の前に持ってくる必要があった。そうしないとplt.show()
を明示的に呼び出すと帰ってこない。
DatetimeIndex
オブジェクトにはこれらの日付関係のプロパティーがあり、使いやすいスライス操作をサポートする。特に
.index
から.year
や.weekday
などにアクセスできる。
.resample()
は時系列の頻度を変える強力なメソッドだ。.groupby()
に似ている。"M"
や"5H"
などの対象の頻度を定義する文字列を使ってグループ化する。.resample()
の結果に対して.mean()
や.max()
などの集計メソッドを呼び出す。.freq
にその頻度が保持される。
文字列を操作するには
文字列メソッドは
.str
から利用可能だ。例えば列を一つ選択して、それに対して
.str.lower()
を呼び出す。するとその列名が小文字になったSeries
オブジェクトが得られる。同様にして
.str.split()
などを実行すると文字列からなるリストを要素とするSeries
が生成する。演算子
in
の代わりに.str.contains()
を呼び出す。演算子
len
の代わりに.str.len()
を呼び出す。
文字列メソッドは要素ごとに機能し、条件付きインデックスに対して用いられる。
メソッド
.replace()
は与えられたdict
オブジェクトに従って値を変換する使い勝手のよいメソッドだ。.str.replace()
も別に存在するので注意する。
10 minutes to pandas¶
とても 10 分で履修できるような分量に収まっていない Pandas の紹介記事だ。上述のチュートリアルと併せて読んでもいいし、チュートリアルだけ読んで次に進んでもいい。
Object creation
Series
オブジェクトの直接生成。DataFrame
オブジェクトの直接生成。NumPy の配列オブジェクトとキーワード引数
index
,columns
を与える方法。辞書オブジェクトを与える方法。キーが列名で値が
Series
を生成するデータ。
Viewing data
.head()
.tail()
.index
.columns
.to_numpy()
はインデックスや列名を含まない部分を返す。.describe()
は統計概要を表示する。.T
で行と列を入れ替えた表を得る。NumPy と同じ。.sort_index()
で行または列をソートする。ここでキーワード引数axis
を指定する。axis=0
ならば行を入れ替えるようなソート。axis=1
ならば列を入れ替えるようなソート。
.sort_values()
では基準となる行または列を指定してソートする。キーワード引数by
により基準を指定する。
Selection
冒頭で本番用コードでは、最適化されたアクセスメソッド
.at
,.iat
,.loc
,.iloc
を推奨するとあることに注意。DataFrame
オブジェクトに対して角括弧と列名を指定するとSeries
を参照できる。この角括弧でスライス記法を用いると、対応する行を参照できる。
.loc[]
にインデックスを指定するとその行を参照できる。.loc[indexes, columns]
のような指定方法もできる。
.at[index, column]
を用いれば効率的にデータ中の一要素を参照できる。.iloc[i]
,.iloc[i, j]
,.iloc[i1:i2, j1:j2]
, などによりゼロ起点の添字で参照する。スライス記法も可。.iat[i]
を用いれば効率的にデータ中の一要素を参照できる。Boolean indexing
Series
やDataFrame
とスカラー値を比較演算子で評価した式を角括弧の中に入れる。各要素ごとに評価の結果が真である部分だけが抽出される。.isin()
などのその目的用のメソッドがある。
存在しない列名を角括弧に入れて左辺値とし、値を代入することができる。こうすると新しい列が生じる。
列名だけではなく、上述の角括弧記法すべてが利用可。Boolean index による指定でもよい。
Missing data
Pandas は基本的には
np.nan
を欠損値の表現に採用している。欠損値をオペランドにとる演算はnp.nan
と評価されるのが基本的だ。.reindex()
の機能がこれではよくわからない。.dropna()
で欠損値を含む行を削除する。.fillna()
で欠損値を指定の値で置き換える。関数
isna()
でDataFrame
からマスクを作成することができる。
Operations
さっきも言ったように、データ操作において欠損値は除外される。
.mean()
などの記述統計メソッドの簡単な呼び出し方を習得する。寸法の異なるデータ同士の操作には明示的な alignment を必要とすることを理解する。
.apply()
を使えるようになる(操作を関数の形式で渡すといい)。.value_counts()
で度数分布を得られることを理解する。文字列に関する操作を属性
.str
を経由して行うことができる。
Merge
関数
concat()
でどのように表を連結できるのかを理解する。DataFrame
は列を追加するのは比較的高速だが、行を追加するのはコピー操作を必要とするため高く付く。前述のように
.merge()
で SQL 風の JOIN 操作を実現できる。
Grouping
グループ化の神髄は「分割・適用・結合」だ。
.groupby()
して得られるオブジェクトに対してはだいたい集計メソッドを呼び出すことになると憶えておく。
Reshaping
TODO: ここを読む前に本文のリンク先二箇所を読んでおくこと。
メソッド
.stack()
はDataFrame
の列側の階層を「圧縮」する。このデモでは列だった A と B がインデックスのいちばん右に移っている。この逆演算が
.unstack()
だ。デフォルトではいちばん右の(最下層ということ)インデックスを列側に移す。引数は左(最上層)からの序数を指定する。関数
pivot_table()
はDataFrame
からピボットテーブルを作成することができる。
Time series
関数
date_range()
を習得する。時系列を表す
Series
に対する.resample()
操作を習得する。特に引数の指定方法。.tz_localize()
はタイムゾーンが特定されていない時系列に対してそれを局所化する。.tz_convert()
はタイムゾーンが指定されている時系列を別のそれの時系列に変換する。.to_period()
はDatetimeIndex
オブジェクトをPeriodIndex
オブジェクトに変換する。.to_timestamp()
はTimestamp
からなるDatetimeIndex
オブジェクトに、周期の開始点でキャストする。.asfreq()
は時系列を指定の周期に変換する。
Categoricals
まず categorical の概念を理解する。
.astype("category")
という操作により単純な型から categorical に変換できる。列
Series
に対して.cat.categories
に取り得る値の集合を設定することができる。このような列をソートすると、値の順序関係はその設定時のリストの格納順序に従う。このような列を
.groupby()
すると、含まれていない要素についても常に表示する。
Plotting
Matplotlib が裏で動いていることは学習した。
.plot()
でデフォルトのプロットを描画する。これはすべての列をプロットする。
Getting data in/out
CSV ファイルの読み書きに対応していることは学んだ。
HDF5 Store という何かの読み書きもサポートしている。
MS Excel ファイルの読み書きも可能。別途サードパーティー製ライブラリーが必要であることを忘れるな。
Gotchas
DataFrame
やSeries
を真偽値として扱うようなことは避ける。
関連ノート¶
Pandas の基礎的依存パッケージおよびオプショナルな依存パッケージに関するノートがいくつかある。
Matplotlib 利用ノート: プロットを調整するのに Matplotlib の知識がそのまま使える。