Python – 無作為抽出(Random Sampling)
最近非常に注目されているCausal Inferenceですが、今回は業務にて頻繁に使用する無作為抽出(Random Sampling)について記載していきます。
1. データ準備
データ準備として、今回はsklearn.datasetsのcalifornia_housingを使用していきます。このデータは回帰用のSampleデータとして使用できますので、必要に応じて使用してみてください。また、pandas.dataframeを使用するので、pandasもimportし、sklearn.datasetsのcalifornia_housingのデータを変数に格納します。
In [1]: import pandas as pd
...: from sklearn.datasets import fetch_california_housing
In [2]: california_housing = fetch_california_housing()
california_housingのデータをpandas.dataframeに変換し、target column「MudHouseVal」をdataframeに追加してデータ準備完了です。
In [3]: df = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)
In [4]: df['MedHouseVal'] = pd.Series(california_housing.target)
...: df.head()
Out[4]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
0 8.3252 41.0 6.984127 1.023810 322.0 2.555556 37.88 -122.23 4.526
1 8.3014 21.0 6.238137 0.971880 2401.0 2.109842 37.86 -122.22 3.585
2 7.2574 52.0 8.288136 1.073446 496.0 2.802260 37.85 -122.24 3.521
3 5.6431 52.0 5.817352 1.073059 558.0 2.547945 37.85 -122.25 3.413
4 3.8462 52.0 6.281853 1.081081 565.0 2.181467 37.85 -122.25 3.422
以上でデータ準備は完了です。
2. 無作為抽出(Random Sampling) – 基礎編
さて、本題の無作為抽出 (Raddom Sampling) を行なってみようと思います。以下がAPI docです。
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sample.html
非常に簡単で、.sample() を使用するだけでランダムサンプリングができてしまいます。
a. 1レコード取得
まず、1レコードを取得してみようと思います。引数のrandom_state=0は、乱数シードを0で固定しています。
In [5]: df.sample(random_state=0)
Out[5]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
14740 4.1518 22.0 5.663073 1.075472 1551.0 4.180593 32.58 -117.05 1.369
次に、先ほど設定した同じ乱数シード0で、実行すると同じレコードが取得されることが確認できます。
In [6]: df.sample(random_state=0)
Out[6]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
14740 4.1518 22.0 5.663073 1.075472 1551.0 4.180593 32.58 -117.05 1.369
b. 複数レコード取得
では、複数レコードをサンプリングしてみます。今回は、5レコード取得してみようと思います。random_stateは先ほどとは別の値を設定します。
In [7]: df.sample(5, random_state=1)
Out[7]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
4712 3.2500 39.0 4.503205 1.073718 1109.0 1.777244 34.06 -118.36 3.550
2151 1.9784 37.0 4.988584 1.038813 1143.0 2.609589 36.78 -119.78 0.707
15927 4.0132 46.0 4.480296 1.012315 1534.0 3.778325 37.73 -122.42 2.294
82 1.5208 52.0 3.908046 1.114943 200.0 2.298851 37.81 -122.28 1.125
8161 5.1795 37.0 5.406360 1.024735 711.0 2.512367 33.82 -118.13 2.254
もちろん同じrandom_stateを指定すれば同じdatasetが取得できます。
In [8]: df.sample(5, random_state=1)
Out[8]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
4712 3.2500 39.0 4.503205 1.073718 1109.0 1.777244 34.06 -118.36 3.550
2151 1.9784 37.0 4.988584 1.038813 1143.0 2.609589 36.78 -119.78 0.707
15927 4.0132 46.0 4.480296 1.012315 1534.0 3.778325 37.73 -122.42 2.294
82 1.5208 52.0 3.908046 1.114943 200.0 2.298851 37.81 -122.28 1.125
8161 5.1795 37.0 5.406360 1.024735 711.0 2.512367 33.82 -118.13 2.254
同じdatasetであることが確認できますね。
3. 無作為抽出(Random Sampling) – 比率で取得
では、RCTが行える際なのに、Treatment group, Control group作成の際によく使用する、比率での抽出を行なってみようと思います。その前に、レコード数を見てみようと思います。
In [9]: df.shape
Out[9]: (20640, 9)
20,640レコード格納されていることが確認できました。
では、比率を指定することで無作為抽出 (Random Sampling) してみようと思います。まずは、frac=.5を指定することで、50% (10,320件)のレコードを取得してみようと思います。
In [10]: df_t = df.sample(frac=.5, random_state=2)
...: df_t
Out[10]:
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude MedHouseVal
10385 6.4114 15.0 7.527559 1.049869 2529.0 3.318898 33.60 -117.65 2.787
1943 4.1843 12.0 6.330084 1.041783 2033.0 2.831476 38.62 -120.91 2.076
7490 1.7411 35.0 5.369159 1.294393 909.0 4.247664 33.93 -118.23 0.967
16889 3.4412 39.0 4.173405 1.074573 2156.0 1.937107 37.59 -122.37 3.538
11416 7.8195 16.0 8.602349 1.058725 2142.0 3.593960 33.70 -117.98 3.905
... ... ... ... ... ... ... ... ... ...
11141 3.7500 19.0 4.473146 1.038363 969.0 2.478261 33.84 -117.95 1.734
6202 3.8837 32.0 5.559719 1.053864 1580.0 3.700234 34.07 -117.89 2.003
2220 6.1175 16.0 7.567282 0.992084 1016.0 2.680739 36.83 -119.82 1.447
14556 7.6348 4.0 6.534079 1.060020 2607.0 2.652085 32.98 -117.24 3.370
2137 2.6767 15.0 4.512448 1.170124 1194.0 2.477178 36.81 -119.72 0.875
[10320 rows x 9 columns]
まとめ
ということで、今回はPython – 無作為抽出(Random Sampling)について記載しました。個人的には、API docに記載されている引数の指定のバリエーションを全て使用することはあまりないので、記載していませんが、時間のある時にAPI docを見てみてもよいかと思います。