Разделение фрейма данных на обучающие и тестовые наборы в R - PullRequest
0 голосов
/ 03 мая 2018

У меня есть следующие data.frame:

>str(customerduration_data)

Classes 'tbl_df', 'tbl' and 'data.frame':   4495 obs. of  4 variables:

$ monthofgateOUT    : Ord.factor w/ 4 levels "8"<"9"<"10"<"11": 1 1 1 1 1 1 1 1 1 1 ...

$ dayofgateOUT      : Ord.factor w/ 7 levels "Monday"<"Tuesday"<..: 4 5 1 1 1 1 1 2 2 3 ...

$ timeofgateOUT     : Ord.factor w/ 20 levels "3"<"4"<"5"<"6"<..: 13 4 2 3 3 11 15 10 13 14 ...

$ durationCUST_hours: num  95.63 5.73 10.73 10.2 14.4 .

Я хочу разделить эти данные на обучающий и тестовый набор, используя следующую команду:

install.packages("caTools")

library (caTools)

set.seed(6)

customerduration_data$spl=sample.split(customerduration_data,SplitRatio=0.7)

Однако после выполнения вышеуказанной команды возникает следующая ошибка:

>Error in `$<-.data.frame`(`*tmp*`, spl, value = c(TRUE, FALSE, FALSE,  : 
  replacement has 4 rows, data has 4495

Как я могу решить эту проблему?

Ответы [ 4 ]

0 голосов
/ 03 мая 2018

Вот альтернатива, использующая пакет caret и его функцию createDataPartition(). Мы будем использовать данные о болезни Альцгеймера из пакета Applied Predictive Modeling, чтобы проиллюстрировать создание тестовых и обучающих наборов данных.

library(AppliedPredictiveModeling)
library(caret)
data(AlzheimerDisease)
adData <- data.frame(diagnosis, predictors)
# count rows in data frame
nrow(adData)
trainIndex <- createDataPartition(diagnosis, p = .75,list=FALSE)
training <- adData[trainIndex,]
testing <- adData[-trainIndex,]
# rows in training data frame
nrow(training)
# rows in testing data frame 
nrow(testing)

... и вывод:

> library(AppliedPredictiveModeling)
> library(caret)
Loading required package: lattice
Loading required package: ggplot2
> data(AlzheimerDisease)
> adData <- data.frame(diagnosis, predictors)
> # count rows in data frame
> nrow(adData)
[1] 333
> trainIndex <- createDataPartition(diagnosis, p = .75,list=FALSE)
> training <- adData[trainIndex,]
> testing <- adData[-trainIndex,]
> # rows in training data frame
> nrow(training)
[1] 251
> # rows in testing data frame 
> nrow(testing)
[1] 82
> 
0 голосов
/ 03 мая 2018

Вы создаете столбец индекса в исходном фрейме data.frame. Если вы хотите разделить df на два набора, train и test, вы можете сделать следующее.

library(caTools)

set.seed(6)    # make the results reproducible

inx <- sample.split(seq_len(nrow(customerduration_data)), 0.7)
train <- customerduration_data[inx, ]
test <-  customerduration_data[!inx, ]

Это не создает столбец spl. Чтобы создать его, используйте ответ @ RalfStubner.

РЕДАКТИРОВАТЬ.

Другой способ - использовать sample с вектором вероятностей.

inx2 <- sample(c(FALSE, TRUE), 4495, replace = TRUE, prob = c(0.3, 0.7))

Пока тестирую три решения, я получаю следующие результаты.

microbenchmark::microbenchmark(
  base_griffinevo = sample(c(rep(TRUE, floor(0.7*4495)), rep(FALSE, 4495-floor(0.7*4495))), replace = F),
  base_Rui = sample(c(FALSE, TRUE), 4495, replace = TRUE, prob = c(0.3, 0.7)),
  caTools_Ralf = sample.split(seq_len(nrow(customerduration_data)), 0.7)
)
#Unit: microseconds
#            expr     min       lq      mean  median        uq      max neval
# base_griffinevo 177.072 183.7665  219.3547 195.147  239.6660  523.851   100
#        base_Rui  89.708  93.2225  119.4083 119.666  134.5615  253.389   100
#    caTools_Ralf 838.495 861.4235 1103.0870 926.361 1313.1390 3634.478   100

Таким образом, более простой, базовый путь R также самый быстрый.

0 голосов
/ 03 мая 2018

В качестве альтернативы вы можете использовать base R , что дает более быстрый вариант (3,4 x в соответствии с microbenchmark) и не требует дополнительных пакетов:

df$spl <- sample(c(rep(TRUE, floor(0.7*4495)), rep(FALSE, 4495-floor(0.7*4495))), replace = F)

Разделение на наборы данных как:

df$spl <- sample(c(rep(TRUE, floor(0.7*4495)), rep(FALSE, 4495-floor(0.7*4495))), replace = F)
test_data  <- df[df[,'spl'] %in% TRUE, ]
train_data <- df[df[,'spl'] %in% FALSE, ]
0 голосов
/ 03 мая 2018

Функция sample.split ожидает вектор. Вот простой способ добиться этого:

library(caTools)
customerduration_data$spl <- sample.split(seq_len(nrow(customerduration_data)), 
                                          SplitRatio = 0.7)
...