サンプル関数を使用してデータをトレーニング/テストセットに分割する方法


160

Rを使い始めたばかりで、データセットを次のサンプルコードに組み込む方法がわかりません。

sample(x, size, replace = FALSE, prob = NULL)

トレーニング(75%)およびテスト(25%)セットに含める必要があるデータセットがあります。xとサイズにどのような情報を入力すればよいかわかりません。xはデータセットファイルであり、サンプルのサイズはいくつですか?


1
xのインデックス(行/列番号など)にすることができますdatasizeすることができます0.75*nrow(data)sample(1:10, 4, replace = FALSE, prob = NULL)それが何をするか見てみてください。
harkmug 2013年

回答:


255

データのパーティショニングを実現するためのアプローチは数多くあります。より完全なアプローチについてcreateDataPartitionは、caToolsパッケージ内の関数を見てください。

以下に簡単な例を示します。

data(mtcars)

## 75% of the sample size
smp_size <- floor(0.75 * nrow(mtcars))

## set the seed to make your partition reproducible
set.seed(123)
train_ind <- sample(seq_len(nrow(mtcars)), size = smp_size)

train <- mtcars[train_ind, ]
test <- mtcars[-train_ind, ]

このコードが一意のテストを返してdfをトレーニングすることを保証するものは少し混乱していますか?うまくいくようですが、誤解しないでください。インデックスの減算がユニークな観測につながる方法を理解するのに苦労しているだけです。たとえば、10行1列のdfがあり、その1列に1、2、3、4、5、6、7、8、9、10が含まれていて、このコードに従っている場合、列車がインデックス4と-6-> 10-6 = 4のテスト
goldisfine 2014

1
感謝。試しましたがmtcars[!train_ind]、失敗しませんでしたが、期待どおりに動作しませんでした。どのようにしてサブセットを使用でき!ますか?
user989762 2015

@ user989762 !は、論理(TRUE/FALSE)に使用され、インデックスには使用されません。を使用してサブセット化する場合は!、mtcars [ !seq_len(nrow(mtcars)) %in% train_ind、](テストされていません)などを試してください。
ディコア2015

1
@VedaadShakibは、「-」を使用すると、train_ind内のすべてのインデックスをデータから除外します。見てくださいadv-r.had.co.nz/Subsetting.htmlを。それがお役に立て
ば幸い

1
ではないcreateDataPartitioncaretしていませんかcaTools
J. Mini

93

次の方法で簡単に実行できます。

set.seed(101) # Set Seed so that same sample can be reproduced in future also
# Now Selecting 75% of data as sample from total 'n' rows of the data  
sample <- sample.int(n = nrow(data), size = floor(.75*nrow(data)), replace = F)
train <- data[sample, ]
test  <- data[-sample, ]

caToolsパッケージを使用して:

require(caTools)
set.seed(101) 
sample = sample.split(data$anycolumn, SplitRatio = .75)
train = subset(data, sample == TRUE)
test  = subset(data, sample == FALSE)

4
私は最近MITでコースを行いましたが、彼らはcaToolsを使用するアプローチを全体的に使用しました。ありがとう
Chetan Sharma

1
sample = sample.split(data[,1], SplitRatio = .75)列に名前を付ける必要がなくなります。
ベンジャミンジーパート

33

これを使用dplyrすると、非常に簡単になります。データセットにid変数が必要です。これは、セットの作成だけでなく、プロジェクト中のトレーサビリティのためにも、とにかく良いアイデアです。含まれていない場合は追加してください。

mtcars$id <- 1:nrow(mtcars)
train <- mtcars %>% dplyr::sample_frac(.75)
test  <- dplyr::anti_join(mtcars, train, by = 'id')

28

これはほとんど同じコードですが、より見栄えが良いです

bound <- floor((nrow(df)/4)*3)         #define % of training and test set

df <- df[sample(nrow(df)), ]           #sample rows 
df.train <- df[1:bound, ]              #get training set
df.test <- df[(bound+1):nrow(df), ]    #get test set

うん!おしゃれ!
MeenakshiSundharam

23
library(caret)
intrain<-createDataPartition(y=sub_train$classe,p=0.7,list=FALSE)
training<-m_train[intrain,]
testing<-m_train[-intrain,]

3
コードのみの答えは答えですが、いくつかの説明を提供することをお勧めします。
C8H10N4O2 2016

m_trainとは つまり、元のdata.frameをサブトレーニングします。したがって、改訂されたコードは、トレーニング<-sub_train [intrain、]およびテスト<-sub_train [-intrain、]である必要があります。過去5年間で、この大きな問題を誰もあなたの答えで見つけることができなかったのはなぜでしょうか。
mnm 2016

21

「a」をトレイン(70%)とテスト(30%)に分割します

    a # original data frame
    library(dplyr)
    train<-sample_frac(a, 0.7)
    sid<-as.numeric(rownames(train)) # because rownames() returns character
    test<-a[-sid,]

できた


4
dpyrパッケージをインポートする必要がある、require(dplyr)
TheMI

この回答は役に立ちましたが、期待される結果を得るために微調整する必要がありました。そのまま、データセット「train」には行名= sidの連続した整数があります:1,2,3,4、... sidを元のデータセット「a」からの行番号にする必要があります。連続した整数ではありません。したがって、最初に 'a'にid変数を作成する必要があります。
スコットマーフ2016年

row.names(mtcars)<-NULL; train <-dplyr :: sample_frac(mtcars、0.5); test <-mtcars [-as.numeric(row.names(train))、]#データに対してこれを実行しました。行名がすでに数値に設定されている場合、元のコードは機能しません
Christopher John

16

私の解決策は基本的にディコアと同じですが、解釈が少し簡単です:

data(mtcars)
n = nrow(mtcars)
trainIndex = sample(1:n, size = round(0.7*n), replace=FALSE)
train = mtcars[trainIndex ,]
test = mtcars[-trainIndex ,]

可変スイスとは何ですか?
billmccord

7

素晴らしいdplyrライブラリを使用した、より簡潔でシンプルな方法:

library(dplyr)
set.seed(275) #to get repeatable data

data.train <- sample_frac(Default, 0.7)

train_index <- as.numeric(rownames(data.train))
data.test <- Default[-train_index, ]

1
Default[-train_index,]最後の行に使用するつもりでしたか?
Matt L.

5

入力した場合:

?sample

は、サンプル関数のパラメーターの意味を説明するヘルプメニューを起動します。

私は専門家ではありませんが、ここに私が持っているいくつかのコードがあります:

data <- data.frame(matrix(rnorm(400), nrow=100))
splitdata <- split(data[1:nrow(data),],sample(rep(1:4,as.integer(nrow(data)/4))))
test <- splitdata[[1]]
train <- rbind(splitdata[[1]],splitdata[[2]],splitdata[[3]])

これにより、トレーニングが75%、テストが25%になります。


5

ここに掲載されているさまざまな方法をすべて調べた後、TRUE/FALSEデータの選択と選択解除に利用している人は誰もいませんでした。だからその手法を活かした方法を共有したいと思いました。

n = nrow(dataset)
split = sample(c(TRUE, FALSE), n, replace=TRUE, prob=c(0.75, 0.25))

training = dataset[split, ]
testing = dataset[!split, ]

説明

Rからデータを選択する方法は複数ありますが、最も一般的には、正/負のインデックスを使用してそれぞれ選択/選択解除します。ただし、を使用TRUE/FALSEして選択/選択解除することで、同じ機能を実現できます。

次の例を考えてみましょう。

# let's explore ways to select every other element
data = c(1, 2, 3, 4, 5)


# using positive indices to select wanted elements
data[c(1, 3, 5)]
[1] 1 3 5

# using negative indices to remove unwanted elements
data[c(-2, -4)]
[1] 1 3 5

# using booleans to select wanted elements
data[c(TRUE, FALSE, TRUE, FALSE, TRUE)]
[1] 1 3 5

# R recycles the TRUE/FALSE vector if it is not the correct dimension
data[c(TRUE, FALSE)]
[1] 1 3 5

4

私のソリューションでは、行をシャッフルしてから、行の最初の75%をトレーニングとして使用し、最後の25%をテストとして使用します。超シンプル!

row_count <- nrow(orders_pivotted)
shuffled_rows <- sample(row_count)
train <- orders_pivotted[head(shuffled_rows,floor(row_count*0.75)),]
test <- orders_pivotted[tail(shuffled_rows,floor(row_count*0.25)),]

4

rsampleパッケージの使用を提案できます。

# choosing 75% of the data to be the training data
data_split <- initial_split(data, prop = .75)
# extracting training data and test data as two seperate dataframes
data_train <- training(data_split)
data_test  <- testing(data_split)

3

scorecard パッケージにはそのための便利な機能があり、比率とシードを指定できます

library(scorecard)

dt_list <- split_df(mtcars, ratio = 0.75, seed = 66)

試験列車データがリストに格納され、呼び出すことによってアクセスすることができるdt_list$traindt_list$test


2

list同じサイズのサブサンプルの aを作成する関数の下にあります。これは、正確には望んでいたものではありませんが、他の人にとっては役立つかもしれません。私の場合、より小さいサンプルに複数の分類木を作成して、過適合をテストします。

df_split <- function (df, number){
  sizedf      <- length(df[,1])
  bound       <- sizedf/number
  list        <- list() 
  for (i in 1:number){
    list[i] <- list(df[((i*bound+1)-bound):(i*bound),])
  }
  return(list)
}

例:

x <- matrix(c(1:10), ncol=1)
x
# [,1]
# [1,]    1
# [2,]    2
# [3,]    3
# [4,]    4
# [5,]    5
# [6,]    6
# [7,]    7
# [8,]    8
# [9,]    9
#[10,]   10

x.split <- df_split(x,5)
x.split
# [[1]]
# [1] 1 2

# [[2]]
# [1] 3 4

# [[3]]
# [1] 5 6

# [[4]]
# [1] 7 8

# [[5]]
# [1] 9 10

2

RサンプルコードでcaToolsパッケージを使用すると、次のようになります。

data
split = sample.split(data$DependentcoloumnName, SplitRatio = 0.6)
training_set = subset(data, split == TRUE)
test_set = subset(data, split == FALSE)

2

ベースRを使用します。関数runifは、0から1までの均一に分散された値を生成します。カットオフ値(下の例ではtrain.size)を変化させることにより、カットオフ値より下のランダムレコードの割合が常にほぼ同じになります。

data(mtcars)
set.seed(123)

#desired proportion of records in training set
train.size<-.7
#true/false vector of values above/below the cutoff above
train.ind<-runif(nrow(mtcars))<train.size

#train
train.df<-mtcars[train.ind,]


#test
test.df<-mtcars[!train.ind,]

これは、実際にトレーニングとテストセットを作成するための余分な数行を示した場合(初心者がしばしば苦労する)、はるかに良い答えになります。
グレゴールトーマス

2

仮定すると、DFがあなたのデータフレームであり、あなたが作成することを75%の列車25%のテストを

all <- 1:nrow(df)
train_i <- sort(sample(all, round(nrow(df)*0.75,digits = 0),replace=FALSE))
test_i <- all[-train_i]

次に、トレインを作成してデータフレームをテストします。

df_train <- df[train_i,]
df_test <- df[test_i,]

1
require(caTools)

set.seed(101)            #This is used to create same samples everytime

split1=sample.split(data$anycol,SplitRatio=2/3)

train=subset(data,split1==TRUE)

test=subset(data,split1==FALSE)

sample.split()関数は、データフレームに1つの余分列「split1」を追加すると行の2/3がFALSE.Nowとして、このTRUEとしての価値などsplit1がTRUEである行が列にコピーされ、他の行がテストにコピーされますがありますデータフレーム。


1

私はこれにぶつかりました、それも助けになります。

set.seed(12)
data = Sonar[sample(nrow(Sonar)),]#reshufles the data
bound = floor(0.7 * nrow(data))
df_train = data[1:bound,]
df_test = data[(bound+1):nrow(data),]

1

ここでは、データを特定の比率に分割できます。これは、80%がトレーニングで、20%がテストデータセットです。

ind <- sample(2, nrow(dataName), replace = T, prob = c(0.8,0.2))
train <- dataName[ind==1, ]
test <- dataName[ind==2, ]

0

sample再現可能な結果を​​探す場合は、分割に注意してください。データが少しでも変更されると、使用しても分割は異なりますset.seed。たとえば、データ内のIDの並べ替えられたリストがすべて1から10の間の数値であると想像してください。1つの観測、たとえば4をドロップした場合、場所ごとにサンプリングすると、移動した場所が5〜10になるため、異なる結果が得られます。

別の方法は、ハッシュ関数を使用してIDをいくつかの疑似乱数にマップし、これらの数値のmodでサンプリングすることです。このサンプルは、割り当てが相対的な位置ではなく、各観測のハッシュによって決定されるため、より安定しています。

例えば:

require(openssl)  # for md5
require(data.table)  # for the demo data

set.seed(1)  # this won't help `sample`

population <- as.character(1e5:(1e6-1))  # some made up ID names

N <- 1e4  # sample size

sample1 <- data.table(id = sort(sample(population, N)))  # randomly sample N ids
sample2 <- sample1[-sample(N, 1)]  # randomly drop one observation from sample1

# samples are all but identical
sample1
sample2
nrow(merge(sample1, sample2))

[1] 9999

# row splitting yields very different test sets, even though we've set the seed
test <- sample(N-1, N/2, replace = F)

test1 <- sample1[test, .(id)]
test2 <- sample2[test, .(id)]
nrow(test1)

[1] 5000

nrow(merge(test1, test2))

[1] 2653

# to fix that, we can use some hash function to sample on the last digit

md5_bit_mod <- function(x, m = 2L) {
  # Inputs: 
  #  x: a character vector of ids
  #  m: the modulo divisor (modify for split proportions other than 50:50)
  # Output: remainders from dividing the first digit of the md5 hash of x by m
  as.integer(as.hexmode(substr(openssl::md5(x), 1, 1)) %% m)
}

# hash splitting preserves the similarity, because the assignment of test/train 
# is determined by the hash of each obs., and not by its relative location in the data
# which may change 
test1a <- sample1[md5_bit_mod(id) == 0L, .(id)]
test2a <- sample2[md5_bit_mod(id) == 0L, .(id)]
nrow(merge(test1a, test2a))

[1] 5057

nrow(test1a)

[1] 5057

割り当ては確率的であるため、サンプルサイズは正確に5000ではありませんが、大きな数の法則により、大きなサンプルでは問題になりません。

参照:http : //blog.richardweiss.org/2016/12/25/hash-splits.html および/crypto/20742/statistical-properties-of-hash-functions-when -計算-モジュロ


別の質問のように追加しました:stackoverflow.com/questions/52769681/...
dzeltzer

複数の時系列データからauto.arimaモデルを開発し、1年のデータ、3年のデータ、5、7 ...を各シリーズの2年間隔で使用してモデルを構築し、テストしたい残りのテストセット。フィットしたモデルに必要なものが含まれるようにサブセット化するにはどうすればよいですか?ご協力
ありがとうござい


-2

行と列のRインデックスを使用して、いくつかの行を選択する非常に簡単な方法があります。これにより、行数を指定してデータセットをクリーンに分割できます。たとえば、データの最初の80%としましょう。

Rでは、すべての行と列にインデックスが付けられるため、DataSetName [1,1]は「DataSetName」の最初の列と最初の行に割り当てられた値です。[x、]を使用して行を選択し、[、x]を使用して列を選択できます

たとえば、「data」という便利な名前のデータセットが100行ある場合、次のコマンドを使用して最初の80行を表示できます。

表示(データ[1:80、])

同じ方法で、これらの行を選択し、次を使用してサブセット化できます。

train = data [1:80、]

テスト=データ[81:100、]

これで、データを2つの部分に分割して、リサンプリングすることができなくなりました。早くて簡単。


1
そのようにデータを分割できることは事実ですが、お勧めできません。一部のデータセットは、知らない変数によって順序付けられています。したがって、最初のn行を取得するのではなく、トレーニングと見なされる行をサンプリングするのが最善です。
user5029763

1
テストとトレーニングセットに分離する前にデータをシャッフルすると、提案が機能します。
Hadij
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.