はじめに
deepblueインターン生の中山です。
【列分割・NA操作・サンプリング】PythonとRのデータフレーム操作比較 vol.4の続きの記事です。
今回は短い内容ですが、学習データとテストデータの分割について触れたいと思います。
連載
・【読み込み、要約統計量、行・列選択、代入】PythonとRのデータフレーム操作比較 vol.1
・【列追加、重複削除、列名変更、結合、集約】PythonとRのデータフレーム操作比較 vol.2
・【集計、ソート、縦持ち・横持ち変換】PythonとRのデータフレーム操作比較 vol.3
・【列分割・NA操作・サンプリング】PythonとRのデータフレーム操作比較 vol.4
・【train/test分割】PythonとRのデータフレーム操作比較 vol.5
使ったデータ
使ったデータは、irisデータです。
3クラスの分類を行いたかったので、irisにしました。
データ読み込み
Python
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['Target'] = iris.target_names[iris.target]
R
library(tidyverse)
library(caret)
df <- iris %>%
rename(Target = Species)
データの分割
データの分割方法に関しては、いくつかありますが、ここでは以下の2つを用いて説明します。
Pythonはsklearnのtrain_test_splitが有名で、RはcaretのcreateDataPartitionが有名です。
ここでは、学習データ数を全体の20とし、irisのSpeciesの比率が元データと同じになるように設定しております。
Python | R |
train_test_split() | createDataPartition |
Python: train_test_species
train_test_speciesでは、train_sizeを引数に取ることで、学習データ数を指定できます。また、train_sizeは比率と数どちらにも対応しており、下記コードの0.2の箇所に、30と入れても同じような操作を実行できます。
また、train_sizeをtest_sizeと変更しても、テストデータに対して同じ操作を実行できます。
そして、stratify(層別化の意)にyを入れることで、yの比率を一定にできます。
X = df.drop('Target',axis=1)
y = df[['Target']]
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 0.2, stratify = y)
# 下記でも実行可能
# X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 30, stratify = y)
R: createDataPartition
train_test_speciesでは、pを引数に取ることで、学習データの比率を指定できます。
また、listはデフォルトではTRUEとなっているため、FALSEに帰ることで、train_idをlistではなく、matrixにして得ることができます。個人的にはmatrixが好きなので、下記ではFにしています。
そして、timesはtrain_idを得る回数です。timesがkの時、train_idはk列のmatrixとなって得ることができます。複数回のシミュレーションを実行したいときには便利です。
train_id <- df$Target %>%
createDataPartition(p = 0.2, list = F, times = 1)
X_train <- df[train_id, !(colnames(df) %in% 'Target')]
X_test <- df[-train_id, !(colnames(df) %in% 'Target')]
y_train <- df[train_id, 'Target']
y_test <- df[-train_id, 'Target']
PythonとRでの差異
- データをXとyに分ける箇所が異なります。PythonではXとyに分けてから、抽出を実行します。一方で、Rではデータフレームをそのままに分割を実行できます。
- 学習データ数を指定できるかが変わります。Pythonでは、比率に加えて、int型の値を入れることで学習データ数を指定できます。ただ、Rでは数字を入れることはできず、比率のみの設定となります。
- 繰り返しの回数が異なります。Pythonでは、毎回train_test_splitを実行しますが、createDataPartitionであればtimesに回数を指定する事で、データを得ることができます。
この2つの違いは小さなものなので、正直そこまで気にするほどではないと思います。
注意点
詳細は割愛しますが、Rのirisは、Speciesがfactor型となっています。なので、以下のように2つのSpeciesだけを取得して実行してもエラーが出てしまいます。
df <- iris %>%
rename(Target = Species) %>%
filter(Target == 'setosa'|Target == 'versicolor')
train_id <- df$Target %>%
createDataPartition(p = 0.2, list = F, times = 1)
X_train <- df[train_id, !(colnames(df) %in% 'Target')]
X_test <- df[-train_id, !(colnames(df) %in% 'Target')]
y_train <- df[train_id, 'Target']
y_test <- df[-train_id, 'Target']
# createDataPartition(., p = 0.2, list = FALSE, times = 1) で:
# Some classes have no records ( virginica ) and these will be ignored
このような時は、Targetの型をchr型に変更すると回避できます。
具体的には、下記コードをtrain_idの前に挿入します。
他にもいくつか回避法はありますが、ここでは一例だけ示しておきます。
df$Target <- as.character(df$Target)
結果の確認方法
Python: value_counts()
yの中に含まれるクラスの数をカウントします。
value_counts()でdataframeの中を数えることができます。
print(y_train.value_counts(),'\n')
print(y_test.value_counts())
# Target
# virginica 10
# versicolor 10
# setosa 10
# dtype: int64
# Target
# virginica 40
# versicolor 40
# setosa 40
# dtype: int64
R: fct_count
yの中に含まれるクラスの数をカウントします。
fct_count()でカウントできます。fctとありますが、factorだけでなくcharacterにも適用できます。
fct_count(y_train)
fct_count(y_test)
# A tibble: 3 x 2
# f n
# 1 setosa 10
# 2 versicolor 10
# 3 virginica 10
# A tibble: 3 x 2
# f n
# 1 setosa 40
# 2 versicolor 40
# 3 virginica 40
連載
・【読み込み、要約統計量、行・列選択、代入】PythonとRのデータフレーム操作比較 vol.1
・【列追加、重複削除、列名変更、結合、集約】PythonとRのデータフレーム操作比較 vol.2
・【集計、ソート、縦持ち・横持ち変換】PythonとRのデータフレーム操作比較 vol.3
・【列分割・NA操作・サンプリング】PythonとRのデータフレーム操作比較 vol.4
・【train/test分割】PythonとRのデータフレーム操作比較 vol.5
(著:中山 翔太)
関連記事
Deepblueでは統計やAIの平和的活用を一緒に取り組んでいただける方を募集してます。詳しくはRecruitをご覧ください。