Pandas — data.frame in Python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
iris = sns.load_dataset('iris')
型
https://pandas.pydata.org/pandas-docs/stable/user_guide/dsintro.html
Series
- 1次元の名前付き
np.array()
みたいなもの。 DataFrame
- Seriesを列とする2次元の表。
axis=0
が行(index)で、axis=1
が列(columns)。
DataFrameを時間軸方向に重ねたような3次元構造として
Panel
ってのもあったけど MultiIndex
があれば不要ってことでv0.20からdeprecated、v0.25で削除。
“pan(el)-da(ta)-s” が名前の由来だったのに。
読み書き
pd.read_csv(infile)
sep=','
header='infer'
names=None
index_col=None
usecols=None
df.to_csv(outfile)
sep=','
float_format=None
index=True
基本操作
https://pandas.pydata.org/pandas-docs/stable/10min.html
df.columns
df.index
df.values
df.dtypes
df.head()
df.tail()
https://pandas.pydata.org/pandas-docs/stable/indexing.html
df[['species']] # DataFrame with 1 column
df['species'] # Series
df.species # Series (not recommended)
# label-based
df.loc[0]
df.loc[:,'sepal_width']
# integer-based
df.iloc[0]
df.iloc[:,1]
# fast scalar (single value) lookup
df.at[0,'sepal_width']
df.iat[0,1]
df.species
のような attribute access
は既存のメソッド名(e.g., min
)と被るとダメなので基本的には使わないほうが良さそう。
番号でもラベルでもアクセスできる df.ix[]
もあったが、
曖昧で危険なのでdeprecated.
method chaining
DataFrameを何回も再帰代入するより、メソッドを繋いだほうが書きやすいし読みやすい。 カッコかバックスラッシュを使えばドット前に改行やスペースを入れて整形可能。
(iris.query('species != "setosa"')
.filter(regex='^(?!sepal)')
.assign(petal_area=lambda x: x['petal_length'] * x['petal_width'] * 0.5)
.groupby('species')
.aggregate(np.mean)
.sort_values(['petal_length'], ascending=False)
)
See also dplyr + magrittr on R
変形
Index
df.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
- 指定したcolumnをindexにする。
df.reset_index(level=None, drop=False, inplace=False, ...)
- 現在のindexをcolumn化して、新しいものを振り直す。
df.swaplevel(0, 1, axis=0)
df.reorder_levels([1, 0], axis=0)
df.rename_axis(mapper, axis=0, copy=True, inplace=False)
melt, pivot
Rと同様、列を列として扱う。
df.melt(id_vars=None, value_vars=None, var_name=None, value_name='value', ...)
- 縦長に変形。Rでいう
tidyr::pivot_longer()
。 e.g.,iris.melt('species', var_name='variable', value_name='value')
df.pivot(index=None, columns=None, values=None)
- 横長に変形。Rでいう
tidyr::pivot_wider()
。 動かさない列を指定できないのかな?reshape2::dcast()
のように複数の値をaggregationできる亜種としてdf.pivot_table()
があるけどまあ使わないのが無難か。
molten = iris.reset_index().melt(['index', 'species'])
molten.pivot('index', 'variable') # species columns are redundant
molten.pivot('index', 'variable', 'value') # species column is removed
stack, unstack
MultiIndexを中心に考える。 nested tibble的なイメージ?
df.stack(level=-1, dropna=True)
- 縦長に変形。
melt()
と違って変数名はcolumnにならず、 新しいindexとして最内側に追加される。 そのindexに名前をつけるオプションが欲しかった。 部分的に変形するオプションも無いので、 残したい列を予めindexにしておく必要がある。 df.unstack(level=-1, fill_value=None)
,s.unstack()
- 横長に変形。
展開するindexの階層を指定できる(デフォルトの
-1
は最内側)。
stacked = iris.set_index(['species'], append=True).stack()
stacked.unstack()
# more explicitly
stacked.rename_axis(['id', 'species', 'variable']).unstack('variable')
設定
https://pandas.pydata.org/pandas-docs/stable/options.html
pd.set_option('display.max_rows', 20)
pd.set_option('display.width', None)
ディスプレイ幅は os.get_terminal_size().columns
で明示的に取得してもいい。
misc.
英語の発音としては [pǽndəz] のように濁るのが自然だけど 開発者は pan-duss [pǽndəs] と発音している とのこと。