PandasでBootstrap samplingするためのちょっとしたスクリプト
Bootstrap samplingは、データをサンプルの中から重複を許してランダムに取得して、元とはちょっと違った集団を作り出すのに使われる。 例えばそれを1000回とか繰り返したりして統計をとったりする。
Pandasでやるのにどうしたらいいか考えたのでメモっておく。
アヤメのサンプルを使ってみる
pandasとアヤメのサンプル取得、あとはランダムサンプリングに使う乱数モジュールをインポートする。
import pandas as pd
import random
from sklearn.datasets import load_iris
そしてデータをロードしてpandasのデータフレームにのせる。
iris_dataset = load_iris()
df = pd.DataFrame(data=iris_dataset.data, columns=iris_dataset.feature_names)
df.describe()
でデータを見てみる。
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000 1.199333
std 0.828066 0.435866 1.765298 0.762238
min 4.300000 2.000000 1.000000 0.100000
25% 5.100000 2.800000 1.600000 0.300000
50% 5.800000 3.000000 4.350000 1.300000
75% 6.400000 3.300000 5.100000 1.800000
max 7.900000 4.400000 6.900000 2.500000
そしてデータをランダムサンプリングする関数を定義する。
まず元のデータフレームのcolumns
を使って空のデータフレームをpd.DataFrame(columns=a_data_frame.columns)
で作成し、そこに乱数selected_num = random.choice(range(a_data_frame.shape[0]))
で選ばれた行のフレームa_data_frame[selected_num : selected_num + 1]
をappend
で追加していく。
pandasのdata frameでは単行を選択(たとえばnumpyなら[0])するのにも範囲選択([0:1])する必要があるみたいなので注意。
def btstrap(a_data_frame):
btstr_data = pd.DataFrame(columns=a_data_frame.columns)
for a_data in range(a_data_frame.shape[0]):
selected_num = random.choice(range(a_data_frame.shape[0]))
btstr_data = btstr_data.append(a_data_frame[selected_num : selected_num + 1])
return btstr_data
btstr_data = btstrap(df)
とかやってランダムサンプリング後のデータをbtstr_data.describe()
で確認。
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
count 150.000000 150.000000 150.000000 150.000000
mean 5.750000 3.040667 3.660667 1.176000
std 0.728034 0.410287 1.716634 0.766644
min 4.300000 2.000000 1.100000 0.100000
25% 5.100000 2.800000 1.500000 0.200000
50% 5.700000 3.000000 4.250000 1.300000
75% 6.300000 3.300000 5.000000 1.800000
max 7.700000 4.400000 6.700000 2.500000
これを1000回とかループで回してフィッティングなり変数選択なりした結果を取得する。
【後述】もっと簡単な方法があった
replace=True
とすればpandasにもともとある機能の.sample
で同じことができるみたい。
@nkay さんご指摘ありがとうございました。
df.sample(n=df.shape[0], replace=True)