よくあるデータの形式として,
- テーブルデータ
- 時系列データ
- テキストデータ
- 画像データ
- 音声データ
- 映像データ
などがありますが,世の中で最も良くあるのは,特に汎用性の高いエクセルのシートで表されるような行列のデータであるテーブルデータと思われます.
このテーブルデータを効率的に操作することができるのが pandas です.
今回は pandas について,ある程度使えるようになるために一部紹介していきます.
今回のコードは,次の github にも載せています.
pandas 概要
pandas(パンダズ)は,テーブルデータを効率的に操作することができ,テキストファイルはもちろんのこと,CSV や JSON, excel ファイルの読み書きについても,簡単なコードで実現できます.
また,jupyter への出力も視覚的にキレイに出力させるのもサポートされており,データ分析には欠かせないライブラリと言えます.
ライブラリのインポートは,公式ドキュメント(https://pandas.pydata.org/)にて pd と省略形でインポートしており,この方法が一般的です.
import pandas as pd
pandas は基本的には,pandas.Series と pandas.DataFrame という 2 つのオブジェクトで操作します.
Series は,行の名称が辞書型のキーのように紐付いていて,テーブルの一つの列として扱うことができます.
DataFrame は,行名と列名がある表形式のデータテーブルを扱うことができます.
Series / DataFrame の生成
Series の生成について,構文とその例は以下です.
Series をなにかの変数として代替させる場合,”ser” が良く用いられます.
pd.Series(data=None, index=None, dtype=None, name=None, copy=False)
- data: 要素として入れられるデータで,リストなどのイテラブルオブジェクトが使用可能
- index: 行の名称で,リストなどのイテラブルオブジェクトが使用可能
- dtype: データタイプで,文字列やタイプが使用可能
- name: Series の名称
- copy: True のときに Series を変更した場合に,元のデータが numpy の 1 次元配列である場合は元のデータも変更される
arr = list(range(10, 13))
ser = pd.Series(data=arr)
ser
# 0 10
# 1 11
# 2 12
# dtype: int64
pd.Series(data=arr, index=["a", "b", "c"], dtype=float, name="age")
# a 10.0
# b 11.0
# c 12.0
# Name: age, dtype: float64
pd.Series(data={"a": 10, "b": 11, "c": 12}, name="age")
# a 10
# b 11
# c 12
# Name: age, dtype: int64
続いて,DataFrame の生成について,構文とその例は以下です.
DataFrame をなにかの変数として代替させる場合,”df” が良く用いられます.
pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)
- data: 多次元配列やイテラブルオブジェクトや辞書や DataFrame
- index: 行の名称で,リストなどのイテラブルオブジェクトが使用可能
- columns: 列の名称で,リストなどのイテラブルオブジェクトが使用可能
- dtype: データタイプで,文字列やタイプが使用可能
- copy: True のときに Series を変更した場合に,元のデータが numpy 配列である場合は元のデータも変更される
df = pd.DataFrame(data=arr)
df
# 0
# 0 10
# 1 11
# 2 12
arr2 = [
[10, 21],
[11, 22],
[12, 23],
]
pd.DataFrame(data=arr2, index=["a", "b", "c"], columns=["A", "B"], dtype=float)
# A B
# a 10.0 21.0
# b 11.0 22.0
# c 12.0 23.0
pd.DataFrame(data={"A": [10, 11, 12], "B": [21, 22, 23]}, index=["a", "b", "c"])
# A B
# a 10 21
# b 11 22
# c 12 23
Series / DataFrame の属性
良く使われるものの内一覧としては以下で,Series と DataFrame で共通するものやしないものがあります.
属性 | Series | DataFrame |
---|---|---|
T | なし | 転置を返す |
at | 指定するインデックスの要素一つにアクセス | 指定するインデックスとカラムの要素一つにアクセス |
columns | なし | カラムを返す |
hasnans | どれかの要素が NaN である場合に True を返す | なし |
iat | 指定する行番号の要素一つにアクセス | 指定する行・列番号の要素一つにアクセス |
iloc | 指定する行番号の要素にアクセス | 指定する行・列番号の要素にアクセス |
index | index 列を返す | <- |
loc | 指定する要素にアクセス | <- |
name | Series の名称を返す | なし |
shape | 形状を返す | <- |
size | 要素数を返す | <- |
values | 要素のみを numpy.ndarray で返す | <- |
上記の属性について,下記で定義する “ser”, “df” を用いて,以下に例を示していきます.
ser = pd.Series(data={"a": 10, "b": 11, "c": 12}, name="series_abc")
ser
# a 10
# b 11
# c 12
# Name: series_abc, dtype: int64
df = pd.DataFrame(data={"A": [10, 11, 12], "B": [20, 21, 22], "C": ["a", "b", "c"]})
df
# A B C
# 0 10 20 a
# 1 11 21 b
# 2 12 22 c
.T : 転置
df.T
# 0 1 2
# A 10 11 12
# B 20 21 22
# C a b c
.at : 指定するインデックスやカラムの要素一つにアクセス
ser.at["b"]
# 11
df.at[1,"C"]
# 'b'
.columns : カラムを返す
df.columns
# Index(['A', 'B', 'C'], dtype='object')
.hasnans : どれかの要素が NaN である場合に True を返す
ser.hasnans
# False
.iat : 指定する行番号や列番号の要素一つにアクセス
ser.iat[1]
# 11
df.iat[1, 2]
# 'b'
.iloc : 指定する行番号や列番号の要素にアクセス
ser.iloc[1:]
# b 11
# c 12
# Name: series_abc, dtype: int64
df.iloc[1:, 1:]
# B C
# 1 21 b
# 2 22 c
.index : index を返す
ser.index
# Index(['a', 'b', 'c'], dtype='object')
df.index
# RangeIndex(start=0, stop=3, step=1)
.loc : 指定する要素にアクセス
ser.loc[["b","c"]]
# b 11
# c 12
# Name: series_abc, dtype: int64
df.loc[[1, 2], ["B", "C"]]
# B C
# 1 21 b
# 2 22 c
.name : Series の名称を返す
ser.name
# 'series_abc'
.shape : 形状を返す
ser.shape
# (3,)
df.shape
# (3, 3)
.size : 要素数を返す
ser.size
# 3
df.size
# 9
.values : 要素のみを numpy.ndarray で返す
ser.values
# array([10, 11, 12], dtype=int64)
df.values
# array([[10, 20, 'a'],
# [11, 21, 'b'],
# [12, 22, 'c']], dtype=object)
Series / DataFrame のメソッド
良く使われるものの内一覧としては以下で,Series と DataFrame で共通するものやしないものがあります.
このとおり,メソッドだけでも多くのテーブルデータの操作が可能です.
メソッド | Series | DataFrame |
---|---|---|
.abs() | 各要素の絶対値を返す | <- |
.all(axis=0, bool_only=None, skipna=True, level=None) | 全ての要素が True の場合に True を返す | <- |
.any(axis=0, bool_only=None, skipna=True, level=None) | ある要素が True の場合に True を返す | <- |
.argmax(axis=None, skipna=True) | 要素が最大となる index を返す | なし |
.argmin(axis=None, skipna=True) | 要素が最小となる index を返す | なし |
.astype(dtype, copy=True, errors=’raise’) | dtype にて指定する型へキャストする | <- |
.autocorr(lag=1) | 指定する要素数のラグを用いた自己相関係数を返す | なし |
.clip(lower=None, upper=None, axis=None, inplace=False) | 要素の値を lower から upper の間にトリムする | <- |
.compare(other, align_axis=1, keep_shape=False, keep_equal=False) | 元のオブジェクトと other にて指定するオブジェクトを比較したものを返す | <- |
.corr(method=’pearson’, min_periods=1) | なし | 各カラムどうしの相関係数を返す(method で “pearson”, “kendall”, “spearman” が選択できる) |
.copy(deep=True) | コピーを作成する.deep=True であれば deep copy を生成 | <- |
.cov(min_periods=None, ddof=1) | なし | カラムどうしの分散を返す |
.describe(percentiles=None, include=None, exclude=None, datetime_is_numeric=False) | オブジェクトの統計量を返す | <- |
.diff(periods=1) | 行の変化率を返す(period で何行分の差を取るかを指定) | <- |
.dot(other) | other にて指定したオブジェクトとのドット積を返す | <- |
.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors=”raise”) | 指定した行・列を削除したオブジェクトを返す | <- |
.drop_duplicates(keep=’first’, inplace=False) | 重複を削除した Series を返す | – |
.drop_duplicates(subset=None, keep=’first’, inplace=False, ignore_index=False) | – | 重複を削除した DataFrame を返す (ignore_index=True にすると返される index がリセットされる) |
メソッド | Series | DataFrame |
---|---|---|
.dropna(axis=0, inplace=False, how=None) | None や NaN を削除したオブジェクトを返す | <- |
.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None) | NaN を value で指定した値に置換 | <- |
.head(n=5) | 上位 n 行目までのオブジェクトを返す | <- |
.idxmax(axis=0, skipna=True) | 最大となる index を返す | <- |
.idxmin(axis=0, skipna=True) | 最小となる index を返す | <- |
.info(verbose=None, buf=None, max_cols=None, memory_usage=None, show_counts=True) | オブジェクトの情報を表示する | <- |
.interpolate(method=’linear’, axis=0, limit=None, inplace=False, limit_direction=None, limit_area=None, downcast=None) | NaN を補間したオブジェクトを返す | <- |
.isin(values) | values で指定した値が要素と同じであれば True, そうでなければ False としたオブジェクトを返す | <- |
.isna() | 要素が NaN であれば True, そうでなければ False としたオブジェクトを返す | <- |
.items() | dict.items() のように index と要素のタプルを返す | カラム名と pd.Series |
.mask(cond, other=nan, inplace=False, axis=None, level=None, errors=NoDefault.no_default, try_cast=NoDefault.no_default) | cond にて指定する条件に一致する要素を other にて指定する値に置換したオブジェクトを返す | <- |
.max(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None) | axis で指定した軸の最大値を返す | <- |
.mean(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None) | axis で指定した軸の平均値を返す | <- |
.median(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None) | axis で指定した軸の中央値を返す | <- |
.min(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None) | axis で指定した軸の最小値を返す | <- |
.notna() | NaN でない要素を True, NaN の要素を False として返す | <- |
メソッド | Series | DataFrame |
---|---|---|
.nunique(dropna=True) | 重複のない要素の数を返す | <- |
.rank(axis=0, method=’average’, numeric_only=NoDefault.no_default, na_option=’keep’, ascending=True, pct=False) | 指定した軸の要素の順序を返す | <- |
.repeat(repeats, axis=None) | 元オブジェクトを repeats に指定した回数分繰り返したオブジェクトを返す | なし |
.replace(to_replace=None, value=NoDefault.no_default, inplace=False, limit=None, regex=False, method=NoDefault.no_default) | to_replace で指定した値を value で指定した値に置換したオブジェクトを返す | <- |
.reset_index(level=None, drop=False, name=NoDefault.no_default, inplace=False) | index を振り直したオブジェクトを返す | <- |
.round(decimals=0) | decimals で指定した桁で要素を丸めたオブジェクトを返す | <- |
.sample(n=None, frac=None, replace=False, weights=None, random_state=None, axis=None, ignore_index=False) | 指定した axis から n 個のサンプルを取得する | <- |
.sort_index(axis=0, level=None, ascending=True, inplace=False, kind=’quicksort’, na_position=’last’, sort_remaining=True, ignore_index=False, key=None) | index をソートしたオブジェクトを返す | <- |
.sort_values(ny, axis=0, ascending=True, inplace=False, kind=’quicksort’, na_position=’last’, ignore_index=False, key=None) | by で指定したでソートしたオブジェクトを返す | <- |
.sum(axis=None, skipna=True, level=None, numeric_only=None, min_count=0) | axis で指定した軸の総和を返す | <- |
.tail(n=5) | 下位 n 行目までのオブジェクトを返す | <- |
.to_csv(path_or_buf=None, sep=’,’, na_rep=”, float_format=None, columns=None, header=True, index=True, index_label=None, mode=’w’, encoding=None, compression=’infer’, quoting=None, quotechar='”‘, line_terminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal=’.’, errors=’strict’, storage_options=None) | path_or_buf で指定したファイルに CSV 形式で出力する | <- |
.to_dict(into=<class ‘dict’>) | オブジェクトの辞書型を返す | <- |
.to_excel(excel_writer, sheet_name=’Sheet1′, na_rep=”, float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep=’inf’, verbose=True, freeze_panes=None, storage_options=None) | path_or_buf で指定した名称の excel ファイルを出力する | <- |
.to_json(path_or_buf=None, orient=None, date_format=None, double_precision=10, force_ascii=True, date_unit=’ms’, default_handler=None, lines=False, compression=’infer’, index=True, indent=None, storage_options=None) | path_or_buf で指定した名称の json ファイルを出力する | <- |
.to_list() | Series をリストに変換して返す | なし |
.to_numpy(dtype=None, copy=False, na_value=NoDefault.no_default) | Series を numpy.ndarray に変換して返す | なし |
.to_pickle(path, compression=’infer’, protocol=5, storage_options=None) | .pickle 形式で出力する(compression にてファイル圧縮も可) | <- |
.unique() | 重複のない要素の numpy.ndarray を返す | なし |
.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True) | 行の数をカウントした結果を返す | <- |
.where(cond, other=NoDefault.no_default, inplace=False, axis=None, level=None, errors=NoDefault.no_default, try_cast=NoDefault.no_default) | cond の条件式に合わない要素以外を NaN としたオブジェクトを返す | <- |
メソッドの引数で共通の引数として以下が挙げられ,それぞれ役割があります.
引数 | 意味 |
---|---|
axis | 行もしくは列に対する操作を指定.0: 行,1: 列 |
level | マルチインデックスに対して有効(今回は取り扱わず) |
inplace | メソッド適用後に上書きするかどうかを制御 |
index | 行を index で指定するときに用いる |
columns | 列をカラム名で指定するときに用いる |
skipna | NaN をスキップして処理するかどうか |
cond | condition の略で条件式 |
ascending | True だと昇順,False だと降順 |
上記について,下記で定義する “ser”, “df” を用いて,以下に例を示していきます.
ser = pd.Series(data={"a": 10, "b": -10, "c": 0}, name="series_abc")
ser
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df = pd.DataFrame(data={"A": [10, -10, 0], "B": [11, 22, 33]})
df
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
.abs()
・・・・各要素の絶対値を返す
ser.abs()
# a 10
# b 10
# c 0
# Name: series_abc, dtype: int64
df.abs()
# A B
# 0 10 11
# 1 10 22
# 2 0 33
.all(axis=0, bool_only=None, skipna=True, level=None)
・・・・全ての要素が True の場合に True を返す
ser.all()
# False
df.all()
# A False
# B True
# dtype: bool
df.all(axis=1)
# 0 True
# 1 True
# 2 False
# dtype: bool
.any(axis=0, bool_only=None, skipna=True, level=None)
・・・・ある要素が True の場合に True を返す
ser.any()
# True
df.any()
# A True
# B True
# dtype: bool
df.any(axis=1)
# 0 True
# 1 True
# 2 True
# dtype: bool
.argmax(axis=None, skipna=True)
・・・・要素が最大となる index を返す
ser.argmax()
# 0
.argmin(axis=None, skipna=True)
・・・・要素が最小となる index を返す
ser.argmin()
# 1
.astype(dtype, copy=True, errors='raise')
・・・・dtype にて指定する型へキャストする
ser.astype(dtype="float64")
# a 10.0
# b -10.0
# c 0.0
# Name: series_abc, dtype: float64
df.astype(dtype="float64")
# A B
# 0 10.0 11.0
# 1 -10.0 22.0
# 2 0.0 33.0
.autocorr(lag=1)
・・・・指定する要素数のラグを用いた自己相関係数を返す
ser.autocorr()
# -0.9999999999999999
ser.autocorr(lag=0)
# 1.0
.clip(lower=None, upper=None, axis=None, inplace=False)
・・・・要素の値を lower から upper の間にトリムする
ser.clip(lower=1, upper=50)
# a 10
# b 1
# c 1
# Name: series_abc, dtype: int64
df.clip(lower=1, upper=10)
# A B
# 0 10 10
# 1 1 10
# 2 1 10
.compare(other, align_axis=1, keep_shape=False, keep_equal=False)
・・・・元のオブジェクトと other にて指定するオブジェクトを比較したものを返す
s1 = pd.Series(["a", "b", "c", "d", "e"])
s2 = pd.Series(["a", "a", "c", "b", "e"])
s1.compare(other=s2)
# self other
# 1 b a
# 3 d b
s1.compare(other=s2, align_axis=0)
# 1 self b
# other a
# 3 self d
# other b
# dtype: object
s1.compare(other=s2, keep_shape=True)
# self other
# 0 NaN NaN
# 1 b a
# 2 NaN NaN
# 3 d b
# 4 NaN NaN
df
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
.corr(method='pearson', min_periods=1)
・・・・各カラムどうしの相関係数を返す(method で "pearson", "kendall", "spearman" が選択できる
df.corr()
# A B
# A 1.0 -0.5
# B -0.5 1.0
.copy(deep=True)
・・・・コピーを作成する.deep=True であれば deep copy を生成
df2 = df.copy()
df2.iat[0,0] = -777
df2.iat[1,1] = -777
df2
# A B
# 0 -777 11
# 1 -10 -777
# 2 0 33
df.compare(other=df2)
# A B
# self other self other
# 0 10.0 -777.0 NaN NaN
# 1 NaN NaN 22.0 -777.0
df.compare(other=df2, align_axis=0)
# A B
# 0 self 10.0 NaN
# other -777.0 NaN
# 1 self NaN 22.0
# other NaN -777.0
df.compare(other=df2, keep_shape=True)
# A B
# self other self other
# 0 10.0 -777.0 NaN NaN
# 1 NaN NaN 22.0 -777.0
# 2 NaN NaN NaN NaN
.cov(min_periods=None, ddof=1)
・・・・カラムどうしの分散を返す
df.cov()
# A B
# A 100.0 -55.0
# B -55.0 121.0
.describe(percentiles=None, include=None, exclude=None, datetime_is_numeric=False)
・・・・オブジェクトの統計量を返す
ser.describe()
# count 3.0
# mean 0.0
# std 10.0
# min -10.0
# 25% -5.0
# 50% 0.0
# 75% 5.0
# max 10.0
# Name: series_abc, dtype: float64
ser.describe(percentiles=[0.1, 0.2, 0.3])
# count 3.0
# mean 0.0
# std 10.0
# min -10.0
# 10% -8.0
# 20% -6.0
# 30% -4.0
# 50% 0.0
# max 10.0
# Name: series_abc, dtype: float64
df.describe()
# A B
# count 3.0 3.0
# mean 0.0 22.0
# std 10.0 11.0
# min -10.0 11.0
# 25% -5.0 16.5
# 50% 0.0 22.0
# 75% 5.0 27.5
# max 10.0 33.0
.diff(periods=1)
・・・・行の変化率を返す(period で何行分の差を取るかを指定)
ser.diff()
# a NaN
# b -20.0
# c 10.0
# Name: series_abc, dtype: float64
df.diff()
# A B
# 0 NaN NaN
# 1 -20.0 11.0
# 2 10.0 11.0
df.diff(periods=2)
# A B
# 0 NaN NaN
# 1 NaN NaN
# 2 -10.0 22.0
.dot(other)
・・・・other にて指定したオブジェクトとのドット積を返す
ser.dot(ser)
# 200
df.shape
# (3, 2)
df.dot(df.T)
# 0 1 2
# 0 221 142 363
# 1 142 584 726
# 2 363 726 1089
df.T.dot(df)
# A B
# A 200 -110
# B -110 1694
.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors="raise")
・・・・指定した行・列を削除したオブジェクトを返す
ser.drop(labels=["a", "c"])
# b -10
# Name: series_abc, dtype: int64
ser.drop(index=["a", "c"])
# b -10
# Name: series_abc, dtype: int64
存在しない index を指定するとエラーが出ますが,errors に “ignore” をしていすると,指定した index が存在しなくてもエラーが出ず,元のオブジェクトが返されます.
# ser.drop(index=["d"])
# ---------------------------------------------------------------------------
# KeyError Traceback (most recent call last)
# ~\AppData\Local\Temp\ipykernel_14676\1810636668.py in <module>
# ----> 1 ser.drop(index=["d"])
# ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\util\_decorators.py in wrapper(*args, **kwargs)
# 309 stacklevel=stacklevel,
# 310 )
# --> 311 return func(*args, **kwargs)
# 312
# 313 return wrapper
# ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\series.py in drop(self, labels, axis, index, columns, level, inplace, errors)
# 4769 dtype: float64
# 4770 """
# -> 4771 return super().drop(
# 4772 labels=labels,
# 4773 axis=axis,
# ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py in drop(self, labels, axis, index, columns, level, inplace, errors)
# 4277 for axis, labels in axes.items():
# 4278 if labels is not None:
# -> 4279 obj = obj._drop_axis(labels, axis, level=level, errors=errors)
# 4280
# 4281 if inplace:
# ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py in _drop_axis(self, labels, axis, level, errors, consolidate, only_slice)
# 4321 new_axis = axis.drop(labels, level=level, errors=errors)
# 4322 else:
# -> 4323 new_axis = axis.drop(labels, errors=errors)
# 4324 indexer = axis.get_indexer(new_axis)
# 4325
# ~\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\indexes\base.py in drop(self, labels, errors)
# 6642 if mask.any():
# 6643 if errors != "ignore":
# -> 6644 raise KeyError(f"{list(labels[mask])} not found in axis")
# 6645 indexer = indexer[~mask]
# 6646 return self.delete(indexer)
# KeyError: "['d'] not found in axis"
ser.drop(index=["d"], errors="ignore")
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df.drop(index=[0, 2], columns=["A"])
# B
# 1 22
.drop_duplicates(keep='first', inplace=False)
・・・・重複を削除した Series を返す
ser_tmp = pd.Series(data=["a", "b", "a", "a", "b", "c", "a", "b"])
ser_tmp
# 0 a
# 1 b
# 2 a
# 3 a
# 4 b
# 5 c
# 6 a
# 7 b
# dtype: object
ser_tmp.drop_duplicates()
# 0 a
# 1 b
# 5 c
# dtype: object
ser_tmp.drop_duplicates(keep="last")
# 5 c
# 6 a
# 7 b
# dtype: object
df_tmp = pd.DataFrame(data={"A": [1,0,0], "B": [0,1,0], "C": [0,0,1]})
df_tmp
# A B C
# 0 1 0 0
# 1 0 1 0
# 2 0 0 1
df_tmp.drop_duplicates(subset=["C"])
# A B C
# 0 1 0 0
# 2 0 0 1
df_tmp.drop_duplicates(subset=["C"], ignore_index=True)
# A B C
# 0 1 0 0
# 1 0 0 1
.dropna(axis=0, inplace=False, how=None)
・・・・None や NaN を削除したオブジェクトを返す
import math
import numpy as np
ser_nan = pd.Series(data=[None, 1, pd.NA, math.nan, np.nan, math.nan, np.NaN, np.NAN])
ser_nan
# 0 None
# 1 1
# 2 <NA>
# 3 NaN
# 4 NaN
# 5 NaN
# 6 NaN
# 7 NaN
# dtype: object
ser_nan.dropna()
# 1 1
# dtype: object
df_nan = pd.DataFrame(
data={
"A": [1, math.nan, 0],
"B": [math.nan, math.nan, math.nan],
"C": [0, math.nan, math.nan],
},
)
df_nan
# A B C
# 0 1.0 NaN 0.0
# 1 NaN NaN NaN
# 2 0.0 NaN NaN
df_nan.dropna()
# A B C
df_nan.dropna(how="all")
# A B C
# 0 1.0 NaN 0.0
# 2 0.0 NaN NaN
df_nan.dropna(how="all", axis=1)
# A C
# 0 1.0 0.0
# 1 NaN NaN
# 2 0.0 NaN
df_nan.dropna(subset=["C"])
# A B C
# 0 1.0 NaN 0.0
.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
・・・・NaN を value で指定した値に置換
ser_nan.fillna(value=100)
# 0 100
# 1 1
# 2 100
# 3 100
# 4 100
# 5 100
# 6 100
# 7 100
# dtype: int64
df_nan.fillna(value=100)
# A B C
# 0 1.0 100.0 0.0
# 1 100.0 100.0 100.0
# 2 0.0 100.0 100.0
.head(n=5)
・・・・上位 n 行目までのオブジェクトを返す
ser.head()
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df.head(2)
# A B
# 0 10 11
# 1 -10 22
.idxmax(axis=0, skipna=True)
・・・・最大となる index を返す
ser.idxmax()
# 'a'
df
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
df.idxmax()
# A 0
# B 2
# dtype: int64
df.idxmax(axis=1)
# 0 B
# 1 B
# 2 B
# dtype: object
.idxmin(axis=0, skipna=True)
・・・・最小となる index を返す
ser.idxmin()
# 'b'
df.idxmin()
# A 1
# B 0
# dtype: int64
.info(verbose=None, buf=None, max_cols=None, memory_usage=None, show_counts=True)
・・・・オブジェクトの情報を表示する
ser.info()
# <class 'pandas.core.series.Series'>
# Index: 3 entries, a to c
# Series name: series_abc
# Non-Null Count Dtype
# -------------- -----
# 3 non-null int64
# dtypes: int64(1)
# memory usage: 156.0+ bytes
df.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 3 entries, 0 to 2
# Data columns (total 2 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 A 3 non-null int64
# 1 B 3 non-null int64
# dtypes: int64(2)
# memory usage: 176.0 bytes
.interpolate(method='linear', axis=0, limit=None, inplace=False, limit_direction=None, limit_area=None, downcast=None)
・・・・NaN を補間
ser_tmp = pd.Series([0, 1, math.nan, 2, 3, math.nan])
ser_tmp.interpolate()
# 0 0.0
# 1 1.0
# 2 1.5
# 3 2.0
# 4 3.0
# 5 3.0
# dtype: float64
df_nan.interpolate()
# A B C
# 0 1.0 NaN 0.0
# 1 0.5 NaN 0.0
# 2 0.0 NaN 0.0
.isin(values)
・・・・values で指定した値がオブジェクトに入っていれば True, そうでなければ False を返す(values は set, list, tuple などを受け付け,単一の値は不可)
ser.isin(values=[0])
# a False
# b False
# c True
# Name: series_abc, dtype: bool
df.isin(values=(0, 10))
# A B
# 0 True False
# 1 False False
# 2 True False
.isna()
・・・・要素が NaN であれば True, そうでなければ False としたオブジェクトを返す
ser_nan.isna()
# 0 True
# 1 False
# 2 True
# 3 True
# 4 True
# 5 True
# 6 True
# 7 True
# dtype: bool
df_nan.isna()
# A B C
# 0 False True False
# 1 True True True
# 2 False True True
Series.items()
・・・・dict.items() のように index と要素のタプルを返す
DataFrame.items()
・・・・カラム名と pd.Series のタプルを返す
for k,v in ser.items():
print(k, v)
# a 10
# b -10
# c 0
for k,v in df.items():
print(k)
print(v)
# A
# 0 10
# 1 -10
# 2 0
# Name: A, dtype: int64
# B
# 0 11
# 1 22
# 2 33
# Name: B, dtype: int64
.mask(cond, other=nan, inplace=False, axis=None, level=None, errors=NoDefault.no_default, try_cast=NoDefault.no_default)
・・・・cond にて指定する条件に一致する要素を other にて指定する値に置換したオブジェクトを返す
ser.mask(cond=0 <= ser, other=1)
# a 1
# b -10
# c 1
# Name: series_abc, dtype: int64
df.mask(cond=0 <= df, other=1)
# A B
# 0 1 1
# 1 -10 1
# 2 1 1
.max(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None)
・・・・axis で指定した軸の最大値を返す
ser.max()
# 10
df.max()
# A 10
# B 33
# dtype: int64
df.max(axis=1)
# 0 11
# 1 22
# 2 33
# dtype: int64
.mean(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None)
・・・・axis で指定した軸の平均値を返す
ser.mean()
# 0.0
df.mean()
# A 0.0
# B 22.0
# dtype: float64
df.mean(axis=1)
# 0 10.5
# 1 6.0
# 2 16.5
# dtype: float64
.median(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None)
・・・・axis で指定した軸の中央値を返す
ser.median()
# 0.0
df.median()
# A 0.0
# B 22.0
# dtype: float64
df.median(axis=1)
# 0 10.5
# 1 6.0
# 2 16.5
# dtype: float64
.min(axis=NoDefault.no_default, skipna=True, level=None, numeric_only=None)
・・・・axis で指定した軸の最小値を返す
ser.min()
# -10
df.min()
# A -10
# B 11
# dtype: int64
df.min(axis=1)
# 0 10
# 1 -10
# 2 0
# dtype: int64
.notna()
・・・・NaN でない要素を True, NaN の要素を False として返す
ser_nan.notna()
# 0 False
# 1 True
# 2 False
# 3 False
# 4 False
# 5 False
# 6 False
# 7 False
# dtype: bool
df_nan.notna()
# A B C
# 0 True False True
# 1 False False False
# 2 True False False
Series.nunique(dropna=True)
・・・・重複のない要素の数を返す
DataFrame.nunique(axis=0, dropna=True)
・・・・指定した軸の重複のない要素の数を返す
ser.nunique()
# 3
df.nunique()
# A 3
# B 3
# dtype: int64
df.nunique(axis=1)
# 0 2
# 1 2
# 2 2
# dtype: int64
.rank(axis=0, method='average', numeric_only=NoDefault.no_default, na_option='keep', ascending=True, pct=False)
・・・・指定した軸の要素の順序を返す
ser.rank()
# a 3.0
# b 1.0
# c 2.0
# Name: series_abc, dtype: float64
df.rank()
# A B
# 0 3.0 1.0
# 1 1.0 2.0
# 2 2.0 3.0
df.rank(axis=1)
# A B
# 0 1.0 2.0
# 1 1.0 2.0
# 2 1.0 2.0
.repeat(repeats, axis=None)
・・・・元オブジェクトを repeats に指定した回数分繰り返したオブジェクトを返す
ser.repeat(repeats=2)
# a 10
# a 10
# b -10
# b -10
# c 0
# c 0
# Name: series_abc, dtype: int64
.replace(to_replace=None, value=NoDefault.no_default, inplace=False, limit=None, regex=False, method=NoDefault.no_default)
・・・・to_replace で指定した値を value で指定した値に置換したオブジェクトを返す
ser.replace(to_replace=10, value=2222)
# a 2222
# b -10
# c 0
# Name: series_abc, dtype: int64
df.replace(to_replace=10, value=222)
# A B
# 0 222 11
# 1 -10 22
# 2 0 33
.reset_index(level=None, drop=False, name=NoDefault.no_default, inplace=False)
・・・・index を振り直したオブジェクトを返す
ser.reset_index()
# index series_abc
# 0 a 10
# 1 b -10
# 2 c 0
df.reset_index()
# index A B
# 0 0 10 11
# 1 1 -10 22
# 2 2 0 33
.round(decimals=0)
・・・・decimals で指定した桁で要素を丸めたオブジェクトを返す
ser.round(decimals=0)
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df.round(decimals=0)
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
.sample(n=None, frac=None, replace=False, weights=None, random_state=None, axis=None, ignore_index=False)
・・・・指定した axis から n 個のサンプルを取得する
ser.sample(n=2, random_state=0)
# c 0
# b -10
# Name: series_abc, dtype: int64
df.sample(n=2, random_state=0)
# A B
# 2 0 33
# 1 -10 22
df.sample(n=1, random_state=0, axis=1)
# B
# 0 11
# 1 22
# 2 33
.sort_index(axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', sort_remaining=True, ignore_index=False, key=None)
・・・・index をソートしたオブジェクトを返す
ser.sort_index()
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df.sort_index()
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False, key=None)
・・・・指定した index / column でソートしたオブジェクトを返す
ser.sort_values()
# b -10
# c 0
# a 10
# Name: series_abc, dtype: int64
df.sort_values(by="A")
# A B
# 1 -10 22
# 2 0 33
# 0 10 11
df.sort_values(by=0, axis=1, ascending=False)
# B A
# 0 11 10
# 1 22 -10
# 2 33 0
.sum(axis=None, skipna=True, level=None, numeric_only=None, min_count=0)
・・・・axis で指定した軸の総和を返す
ser.sum()
# 0
df.sum()
# A 0
# B 66
# dtype: int64
df.sum(axis=1)
# 0 21
# 1 12
# 2 33
# dtype: int64
.tail(n=5)
・・・・下位 n 行目までのオブジェクトを返す
ser.tail()
# a 10
# b -10
# c 0
# Name: series_abc, dtype: int64
df.tail(2)
# A B
# 1 -10 22
# 2 0 33
.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', line_terminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict', storage_options=None)
・・・・path_or_buf で指定したファイルに CSV 形式で出力する
ser.to_csv("series_0.csv")
ser.to_csv("series_1.csv", index=False)
df.to_csv("dataframe_0.csv")
df.to_csv("dataframe_1.csv", index=False)
.to_dict(into=<class 'dict'>)
・・・・オブジェクトの辞書型を返す
ser.to_dict()
# {'a': 10, 'b': -10, 'c': 0}
df.to_dict()
# {'A': {0: 10, 1: -10, 2: 0}, 'B': {0: 11, 1: 22, 2: 33}}
.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True, freeze_panes=None, storage_options=None)
・・・・path_or_buf で指定した名称の excel ファイルを出力する
ser.to_excel("series.xlsx")
df.to_excel("dataframe.xlsx")
.to_json(path_or_buf=None, orient=None, date_format=None, double_precision=10, force_ascii=True, date_unit='ms', default_handler=None, lines=False, compression='infer', index=True, indent=None, storage_options=None)
・・・・path_or_buf で指定した名称の json ファイルを出力する
ser.to_json("series.json")
df.to_json("dataframe.json", indent=2)
.to_list()
・・・・Series をリストに変換して返す
ser.to_list()
# [10, -10, 0]
.to_numpy(dtype=None, copy=False, na_value=NoDefault.no_default)
・・・・Series を numpy.ndarray に変換して返す
ser.to_numpy()
# array([ 10, -10, 0], dtype=int64)
.to_pickle(path, compression='infer', protocol=5, storage_options=None)
・・・・.pickle 形式で出力する(compression にてファイル圧縮も可)
ser.to_pickle("series.pickle")
df.to_pickle("dataframe.pickle")
df.to_pickle("dataframe.pickle.zip", compression="zip")
.unique()
・・・・重複のない要素の numpy.ndarray を返す
ser_nan.unique()
# array([None, 1, <NA>, nan], dtype=object)
.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True)
・・・・行の数をカウントした結果を返す
ser.value_counts()
# 10 1
# -10 1
# 0 1
# Name: series_abc, dtype: int64
df.value_counts()
# A B
# -10 22 1
# 0 33 1
# 10 11 1
# dtype: int64
.where(cond, other=NoDefault.no_default, inplace=False, axis=None, level=None, errors=NoDefault.no_default, try_cast=NoDefault.no_default)
・・・・cond の条件式に合わない要素以外を NaN としたオブジェクトを返す
ser.where(cond=ser>0)
# a 10.0
# b NaN
# c NaN
# Name: series_abc, dtype: float64
df.where(cond=df>0)
# A B
# 0 10.0 11
# 1 NaN 22
# 2 NaN 33
pandas の関数
例えば,ライブラリを用いずにファイルを読み書きする場合を考えると,いちいちファイル open / close,または with ブロック内で処理を書く必要がありますが,pandas の関数を用いると,少し複雑な処理を加えて読み込んだりする場合もほぼ 1 ラインでコーディングが可能です.
Series / DataFrame のメソッドとかぶるものも多く,以下では,メソッドにない関数で普段遣いのもののみをまとめていきます.
pandas の関数の一部の一覧は以下で,モノによっては引数の種類が膨大なものもありますが,いつも使う引数は限られているので,普段使う実装を記載します.
関数 | 説明 |
---|---|
pd.read_pickle(filepath_or_buffer, compression=’infer’, storage_options=None) | .pickle ファイルを読み込む |
pd.read_csv(filepath_or_buffer, sep=NoDefault.no_default, delimiter=None, header=’infer’, names=NoDefault.no_default, index_col=None, usecols=None, squeeze=None, prefix=NoDefault.no_default, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression=’infer’, thousands=None, decimal=’.’, lineterminator=None, quotechar='”‘, quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors=’strict’, dialect=None, error_bad_lines=None, warn_bad_lines=None, on_bad_lines=None, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None) | .csv ファイルを読み込む |
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, decimal=’.’, comment=None, skipfooter=0, convert_float=None, mangle_dupe_cols=True, storage_options=None) | excel ファイルを読み込む |
pd.read_json(path_or_buf=None, orient=None, typ=’frame’, dtype=None, convert_axes=None, convert_dates=True, keep_default_dates=True, numpy=False, precise_float=False, date_unit=None, encoding=None, encoding_errors=’strict’, lines=False, chunksize=None, compression=’infer’, nrows=None, storage_options=None) | .json ファイルを読み込む |
pd.concat(objs, axis=0, join=’outer’, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True) | objs にて指定する二つの DataFrame を axis 方向に結合する |
pd.read_pickle(filepath_or_buffer, compression='infer', storage_options=None)
・・・・.pickle ファイルを読み込む
pd.read_pickle("dataframe.pickle.zip")
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
pd.read_csv(filepath_or_buffer, sep=NoDefault.no_default, delimiter=None, header='infer', names=NoDefault.no_default, index_col=None, usecols=None, squeeze=None, prefix=NoDefault.no_default, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=None, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None, decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, encoding_errors='strict', dialect=None, error_bad_lines=None, warn_bad_lines=None, on_bad_lines=None, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None)
・・・・.csv ファイルを読み込む
名前のないカラムは “Unnamed: ?” (? は自動的に 0 から順番に割り当てられる数字)として付与されます.
pd.read_csv("dataframe_0.csv")
# Unnamed: 0 A B
# 0 0 10 11
# 1 1 -10 22
# 2 2 0 33
テーブルデータのヘッダとなるカラム名が無い場合は header=None とします.
また,カラム名としたい行が n 行目にある場合(例えば,.csv ファイルの先頭の数行が設定値の説明が記載されていて飛ばして読み込みたい場合)は header=n-1 とします.
pd.read_csv("dataframe_0.csv", header=None)
# 0 1 2
# 0 NaN A B
# 1 0.0 10 11
# 2 1.0 -10 22
# 3 2.0 0 33
pd.read_csv("dataframe_0.csv", header=1)
# 0 10 11
# 0 1 -10 22
# 1 2 0 33
読み込んだ後,列名を変更したい場合は,names にリストやタプルでつけたい名称を渡します.
pd.read_csv("dataframe_0.csv", names=("col0", "col1", "col2"))
# col0 col1 col2
# 0 NaN A B
# 1 0.0 10 11
# 2 1.0 -10 22
# 3 2.0 0 33
読み込んだ後,行名をどこかの列のデータとしたい場合は,index_col に列名を文字型で与えます.
pd.read_csv("dataframe_0.csv", index_col="A")
# Unnamed: 0 B
# A
# 10 0 11
# -10 1 22
# 0 2 33
読み込むファイルでいらないカラムがある場合は,読み込みたいカラム名だけを usecols にタプルやリストで渡すと,不要な列が読み込まれません.
pd.read_csv("dataframe_0.csv", usecols=["A", "B"])
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=None, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, parse_dates=False, date_parser=None, thousands=None, decimal='.', comment=None, skipfooter=0, convert_float=None, mangle_dupe_cols=True, storage_options=None)
・・・・excel ファイルを読み込む
sheet_name にシート名を指定することができ,整数型だとシートの何枚目か,文字型だとシート名を与えることで,読み込むシートを指定できます.
後の引数の扱い方は read_csv とほとんど同じです.
pd.read_excel("dataframe.xlsx", sheet_name=0, index_col=0)
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
pd.read_json(path_or_buf=None, orient=None, typ='frame', dtype=None, convert_axes=None, convert_dates=True, keep_default_dates=True, numpy=False, precise_float=False, date_unit=None, encoding=None, encoding_errors='strict', lines=False, chunksize=None, compression='infer', nrows=None, storage_options=None)
・・・・.json ファイルを読み込む
pd.read_json("./dataframe.json")
# A B
# 0 10 11
# 1 -10 22
# 2 0 33
pd.concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True)
・・・・objs にて指定する二つの DataFrame を axis 方向に結合する
pd.concat(objs=[df, df_nan], axis=0)
# A B C
# 0 10.0 11.0 NaN
# 1 -10.0 22.0 NaN
# 2 0.0 33.0 NaN
# 0 1.0 NaN 0.0
# 1 NaN NaN NaN
# 2 0.0 NaN NaN
pd.concat(objs=[df, df_nan], axis=1)
# A B A B C
# 0 10 11 1.0 NaN 0.0
# 1 -10 22 NaN NaN NaN
# 2 0 33 0.0 NaN NaN
演習問題
- Q.1: フリーの花のアヤメの分類データセットを一つの pandas.DataFrame として定義し,表示させましょう.(https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv にアクセスいただき,web ページ上で右クリックし,メニューから 名前をつけて保存 でローカルに .csv ファイルとして保存できます.scikit-learn がインストール済みであれば datasets.load_iris() でも読み込み可能ですが,その場合は,目的変数のカラム名を “species” とし,目的変数の要素をアヤメの品種も文字列に置き換えてください.)
- Q.2: 説明変数の sepal は花のがく片,petal は花の花弁を表します.上記で生成した DataFrame に,例えば次の特徴量を追加してみましょう.
- がく片を長方形と近似し,”sepal length (cm)” と “sepal width (cm)” を用いて “sepal area (cm^2)” という特徴量を追加しましょう.
- 花弁を長方形と近似し,”petal length (cm)” と “petal width (cm)” を用いて “petal area (cm^2)” という特徴量を追加しましょう.
- Q.3: 上記で生成した DataFrame について,説明変数の各カラムの主要統計量を一行で出してみましょう.
- Q.4: 説明変数の各カラムの主要統計量について,品種別 (“species” ごと) で見てみましょう.ここで,DataFrame の df における “species” カラムの値が “setosa” である部分を抜き取るためには,
df[df["species"]=="setosa"]
とすることで,条件にマッチした DataFrame が返されます.品種の種類はset(df(["species"]))
にて確認できます. - Q.5: 説明変数の相関係数行列を一行で出してみましょう.
- Q.6: 追加した特徴量の “sepal area (cm^2)” はあまり意味がなさそうなので,このカラムを削除しましょう.
- Q.7: 上記まで作成していた DataFrame を別名でコピーしてください.
- Q.8: コピーした DataFrame について,目的変数の “species” 以外のカラムについて 0 ~ 1 へ正規化してください.ここで正規化とは,各カラムの値が最小値 0,最大値 1 へリスケーリングさせることを言い,数列 \(X\) に対し \(i\) 番目の要素 \(x_i\) とすると,要素の最大値 \(x_{max}\) と最小値 \(x_{min}\) を用いて,正規化後の \(i\) 番目の要素の値 \(x_i^+\) は,次で示すことができます.
$$
x_i^+ = \frac{x_i – x_{min}}{x_{max} – x_{min}}
$$
- Q.9: 正規化後の DataFrame について,データの 75 % の行をランダムに抜き取った DataFrame を新たな変数 train に格納し,残りの 25 % の行の DataFrame を新たな変数 test に格納しましょう.
- Q.10: Q.9 にて作成した train, test を pickle 形式かつ圧縮して保存しましょう.
演習問題の解答
- Q.1: フリーの花のアヤメの分類データセットを一つの pandas.DataFrame として定義し,表示させましょう.(https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv にアクセスいただき,web ページ上で右クリックし,メニューから 名前をつけて保存 でローカルに .csv ファイルとして保存できます.scikit-learn がインストール済みであれば datasets.load_iris() でも読み込み可能ですが,その場合は,目的変数のカラム名を “species” とし,目的変数の要素をアヤメの品種も文字列に置き換えてください.)
import pandas as pd
読み込み自体は,次の try ブロック,もしくは,except ブロックどちらでも問題ありません.
try:
from sklearn.datasets import load_iris
iris = load_iris()
print(iris.keys())
df = pd.DataFrame(
data=iris["data"],
columns=iris["feature_names"],
)
df["species"] = [iris["target_names"][i] for i in iris["target"]]
except Exception:
df = pd.read_csv(r"問題の手順で web からダウンロードしてきた iris.csv の絶対パス")
df.tail(3)
# dict_keys(['data', 'target', 'frame', 'target_names', 'DESCR', 'feature_names', 'filename'])
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 0 5.1 3.5 1.4 0.2
# 1 4.9 3.0 1.4 0.2
# 2 4.7 3.2 1.3 0.2
# 3 4.6 3.1 1.5 0.2
# 4 5.0 3.6 1.4 0.2
# .. ... ... ... ...
# 145 6.7 3.0 5.2 2.3
# 146 6.3 2.5 5.0 1.9
# 147 6.5 3.0 5.2 2.0
# 148 6.2 3.4 5.4 2.3
# 149 5.9 3.0 5.1 1.8
#
# species
# 0 setosa
# 1 setosa
# 2 setosa
# 3 setosa
# 4 setosa
# .. ...
# 145 virginica
# 146 virginica
# 147 virginica
# 148 virginica
# 149 virginica
#
# [150 rows x 5 columns]
- Q.2: 説明変数の sepal は花のがく片,petal は花の花弁を表します.上記で生成した DataFrame に,例えば次の特徴量を追加してみましょう.
- がく片を長方形と近似し,”sepal length (cm)” と “sepal width (cm)” を用いて “sepal area (cm^2)” という特徴量を追加しましょう.
- 花弁を長方形と近似し,”petal length (cm)” と “petal width (cm)” を用いて “petal area (cm^2)” という特徴量を追加しましょう.
df["sepal area (cm^2)"] = df["sepal length (cm)"] * df["sepal width (cm)"]
df["petal area (cm^2)"] = df["petal length (cm)"] * df["petal width (cm)"]
print(df.tail(3))
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 147 6.5 3.0 5.2 2.0
# 148 6.2 3.4 5.4 2.3
# 149 5.9 3.0 5.1 1.8
#
# species sepal area (cm^2) petal area (cm^2)
# 147 virginica 19.50 10.40
# 148 virginica 21.08 12.42
# 149 virginica 17.70 9.18
- Q.3: 上記で生成した DataFrame について,説明変数の各カラムの主要統計量を一行で出してみましょう.
print(df.describe())
# sepal length (cm) sepal width (cm) petal length (cm) \
# count 150.000000 150.000000 150.000000
# mean 5.843333 3.057333 3.758000
# std 0.828066 0.435866 1.765298
# min 4.300000 2.000000 1.000000
# 25% 5.100000 2.800000 1.600000
# 50% 5.800000 3.000000 4.350000
# 75% 6.400000 3.300000 5.100000
# max 7.900000 4.400000 6.900000
#
# petal width (cm) sepal area (cm^2) petal area (cm^2)
# count 150.000000 150.000000 150.000000
# mean 1.199333 17.822867 5.794067
# std 0.762238 3.361854 4.712390
# min 0.100000 10.000000 0.110000
# 25% 0.300000 15.660000 0.420000
# 50% 1.300000 17.660000 5.615000
# 75% 1.800000 20.325000 9.690000
# max 2.500000 30.020000 15.870000
- Q.4: 説明変数の各カラムの主要統計量について,品種別 (“species” ごと) で見てみましょう.ここで,DataFrame の df における “species” カラムの値が “setosa” である部分を抜き取るためには,
df[df["species"]=="setosa"]
とすることで,条件にマッチした DataFrame が返されます.品種の種類はset(df(["species"]))
にて確認できます.
species = set(df["species"])
print(species)
# {'virginica', 'versicolor', 'setosa'}
print(df[df["species"]=="setosa"].describe())
# sepal length (cm) sepal width (cm) petal length (cm) \
# count 50.00000 50.000000 50.000000
# mean 5.00600 3.428000 1.462000
# std 0.35249 0.379064 0.173664
# min 4.30000 2.300000 1.000000
# 25% 4.80000 3.200000 1.400000
# 50% 5.00000 3.400000 1.500000
# 75% 5.20000 3.675000 1.575000
# max 5.80000 4.400000 1.900000
#
# petal width (cm) sepal area (cm^2) petal area (cm^2)
# count 50.000000 50.000000 50.000000
# mean 0.246000 17.257800 0.365600
# std 0.105386 2.933775 0.181155
# min 0.100000 10.350000 0.110000
# 25% 0.200000 15.040000 0.280000
# 50% 0.200000 17.170000 0.300000
# 75% 0.300000 19.155000 0.420000
# max 0.600000 25.080000 0.960000
print(df[df["species"]=="versicolor"].describe())
# sepal length (cm) sepal width (cm) petal length (cm) \
# count 50.000000 50.000000 50.000000
# mean 5.936000 2.770000 4.260000
# std 0.516171 0.313798 0.469911
# min 4.900000 2.000000 3.000000
# 25% 5.600000 2.525000 4.000000
# 50% 5.900000 2.800000 4.350000
# 75% 6.300000 3.000000 4.600000
# max 7.000000 3.400000 5.100000
#
# petal width (cm) sepal area (cm^2) petal area (cm^2)
# count 50.000000 50.000000 50.000000
# mean 1.326000 16.526200 5.720400
# std 0.197753 2.866882 1.368403
# min 1.000000 10.000000 3.300000
# 25% 1.200000 14.347500 4.860000
# 50% 1.300000 16.385000 5.615000
# 75% 1.500000 18.495000 6.750000
# max 1.800000 22.400000 8.640000
print(df[df["species"]=="virginica"].describe())
# count 50.00000 50.000000 50.000000
# mean 6.58800 2.974000 5.552000
# std 0.63588 0.322497 0.551895
# min 4.90000 2.200000 4.500000
# 25% 6.22500 2.800000 5.100000
# 50% 6.50000 3.000000 5.550000
# 75% 6.90000 3.175000 5.875000
# max 7.90000 3.800000 6.900000
#
# petal width (cm) sepal area (cm^2) petal area (cm^2)
# count 50.00000 50.000000 50.000000
# mean 2.02600 19.684600 11.296200
# std 0.27465 3.458783 2.157412
# min 1.40000 12.250000 7.500000
# 25% 1.80000 17.430000 9.717500
# 50% 2.00000 20.060000 11.445000
# 75% 2.30000 21.412500 12.790000
# max 2.50000 30.020000 15.870000
3 品種の主要統計量をそれぞれ見比べると,”virginica” が sepal length, petal length / width が大きいことが分かります.
また,”setosa” は他の2品種に比べて petal width / length が極端に小さいことが分かります.
- Q.5: 説明変数の相関係数行列を一行で出してみましょう.
print(df.corr())
# sepal length (cm) sepal width (cm) petal length (cm) \
# sepal length (cm) 1.000000 -0.117570 0.871754
# sepal width (cm) -0.117570 1.000000 -0.428440
# petal length (cm) 0.871754 -0.428440 1.000000
# petal width (cm) 0.817941 -0.366126 0.962865
# sepal area (cm^2) 0.679180 0.643461 0.360909
# petal area (cm^2) 0.857300 -0.288431 0.958422
#
# petal width (cm) sepal area (cm^2) petal area (cm^2)
# sepal length (cm) 0.817941 0.679180 0.857300
# sepal width (cm) -0.366126 0.643461 -0.288431
# petal length (cm) 0.962865 0.360909 0.958422
# petal width (cm) 1.000000 0.368845 0.980333
# sepal area (cm^2) 0.368845 1.000000 0.454503
# petal area (cm^2) 0.980333 0.454503 1.000000
- sepal length, petal length / width はそれぞれ相関が大きいことが示されます.
- sepal width は他の説明変数に対する相関は大きくありません.
- sepal area ですが,他の説明変数との相関も高くなく,追加しましたがあまり意味はなさそうです.
- Q.6: 追加した特徴量の “sepal area (cm^2)” はあまり意味がなさそうなので,このカラムを削除しましょう.
df.drop(columns="sepal area (cm^2)", inplace=True)
print(df.tail(3))
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 147 6.5 3.0 5.2 2.0
# 148 6.2 3.4 5.4 2.3
# 149 5.9 3.0 5.1 1.8
#
# species petal area (cm^2)
# 147 virginica 10.40
# 148 virginica 12.42
# 149 virginica 9.18
- Q.7: 上記まで作成していた DataFrame を別名でコピーしてください.
df_new = df.copy()
- Q.8: コピーした DataFrame について,目的変数の “species” 以外のカラムについて 0 ~ 1 へ正規化してください.ここで正規化とは,各カラムの値が最小値 0,最大値 1 へリスケーリングさせることを言い,数列 \(X\) に対し \(i\) 番目の要素 \(x_i\) とすると,要素の最大値 \(x_{max}\) と最小値 \(x_{min}\) を用いて,正規化後の \(i\) 番目の要素の値 \(x_i^+\) は,次で示すことができます.
$$
x_i^+ = \frac{x_i – x_{min}}{x_{max} – x_{min}}
$$
def normalize(dataframe, column):
dataframe[column] = (
(dataframe[column] - dataframe[column].min())
/ (dataframe[column].max() - dataframe[column].min())
)
return dataframe[column]
df_new["sepal length (cm)"] = normalize(dataframe=df_new, column="sepal length (cm)")
df_new["sepal width (cm)"] = normalize(dataframe=df_new, column="sepal width (cm)")
df_new["petal length (cm)"] = normalize(dataframe=df_new, column="petal length (cm)")
df_new["petal width (cm)"] = normalize(dataframe=df_new, column="petal width (cm)")
df_new["petal area (cm^2)"] = normalize(dataframe=df_new, column="petal area (cm^2)")
print(df_new.tail(3))
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 147 0.611111 0.416667 0.711864 0.791667
# 148 0.527778 0.583333 0.745763 0.916667
# 149 0.444444 0.416667 0.694915 0.708333
#
# species petal area (cm^2)
# 147 virginica 0.652919
# 148 virginica 0.781091
# 149 virginica 0.575508
- Q.9: 正規化後の DataFrame について,データの 75 % の行をランダムに抜き取った DataFrame を新たな変数 train に格納し,残りの 25 % の行の DataFrame を新たな変数 test に格納しましょう.
train = df_new.sample(n=int(len(df_new) * 0.75), random_state=42, axis=0)
print(train.tail(3))
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 63 0.500000 0.375000 0.627119 0.541667
# 54 0.611111 0.333333 0.610169 0.583333
# 126 0.527778 0.333333 0.644068 0.708333
#
# species petal area (cm^2)
# 63 versicolor 0.410533
# 54 versicolor 0.430838
# 126 virginica 0.541244
test = df_new.drop(index=train.index)
print(test.tail(3))
# sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
# 144 0.666667 0.541667 0.796610 1.000000
# 147 0.611111 0.416667 0.711864 0.791667
# 149 0.444444 0.416667 0.694915 0.708333
#
# species petal area (cm^2)
# 144 virginica 0.897208
# 147 virginica 0.652919
# 149 virginica 0.575508
- Q.10: Q.9 にて作成した train, test を pickle 形式かつ圧縮して保存しましょう.
train.to_pickle("./train.pickle.gz", compression="gzip")
test.to_pickle("./test.pickle.gz", compression="gzip")
Python のおすすめの学習方法
プログラミングを最短で習得する,少なくても自分の意志で使えるようになる方法について,いくつかプログラミング言語を触ってきた筆者としては何の言語においても,以下2点が重要だと思います.
- 元々自分が他の言語で作っていた処理を違う言語で書き直す・・・・英語を勉強するときも,脳を生まれたばかりのまっさらな状態から勉強するわけではなく,日本語を通したり対比して,学習済みの言語野を用いて勉強するのと似ています
- 言語自体を網羅的に勉強するのではなく,やりたい事を先に考え,それを達成するために色々と調べながら実装する・・・・例えば,留学で語学力が上達するのは,その国の言葉を使ってコミュニケーションを取ることが強制されるためであり,使うことに対するモチベーションが一番大事です
独学で行うには,やはり2点目の「やりたい事ドリブン学習」が効果的で,例えば次の書籍は,Python を流行らせている AI/データ分析/機械学習/深層学習について実装することに主眼を置き説明されているので,実際に手を動かしながら学んでいける本だと思います(筆者も最初にこちらの書籍で遊びながら学びました).
コメント