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, ]
1
它可以通过以下方式轻松完成:
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, ]
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
mtcars$id <- 1:nrow(mtcars)
train <- mtcars %>% dplyr::sample_frac(.75)
test <- dplyr::anti_join(mtcars, train, by = 'id')
26
我会把'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,]
在创建 list of sub-samples of the same size 的函数下面,这不是您想要的,但可能对其他人有用 . 在我的例子中,在较小的样本上创建多个分类树以测试过度拟合:
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)
}
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,]
18
使用awesome 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, ]
14
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)
# 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)
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))
19 回答
有许多方法可以实现数据分区 . 有关更完整的方法,请查看
caret
包中的createDataPartition
函数 .这是一个简单的例子:
它可以通过以下方式轻松完成:
使用caTools包:
这几乎是相同的代码,但更好看
我会使用
dplyr
,这使它变得非常简单 . 它确实需要数据集中的id变量,这无论如何都是一个好主意,不仅用于创建集合,还用于项目期间的可跟踪性 . 如果不包含它,请添加它 .我会把'a'分成火车(70%)和测试(30%)
DONE
我的解决方案与dickoa基本相同,但更容易理解:
如果您输入:
如果将启动帮助菜单来解释样本函数的参数含义 .
我不是专家,但这里有一些代码:
这将为您提供75%的火车和25%的测试 .
我的解决方案将行洗牌,然后将前75%的行作为列车,将最后25%作为测试 . 超级简单!
在创建 list of sub-samples of the same size 的函数下面,这不是您想要的,但可能对其他人有用 . 在我的例子中,在较小的样本上创建多个分类树以测试过度拟合:
示例:
在R示例代码中使用caTools包将如下: -
使用基数R.函数
runif
生成从0到1的均匀分布值 . 通过变化的截止值(下面的示例中为train.size),您将始终在截止值以下具有大致相同的随机记录百分比 .使用awesome dplyr 库只是一个更简单,更简单的方法:
sample.split()
函数将向数据帧添加一个额外的列'split1',其中2/3的行将此值设置为TRUE而其他行将为FALSE . 否则,split1为TRUE的行将被复制到train中,其他行将被复制到测试数据帧 .我建议使用rsample包:
假设 df 是您的数据框,并且您要创建 75% train 和 25% test
然后创建一个列车并测试数据帧
如果您寻找可重现的结果,请注意
sample
以进行拆分 . 如果您的数据稍有变化,即使您使用set.seed
,分割也会有所不同 . 例如,假设您数据中已排序的ID列表是1到10之间的所有数字 . 如果您只丢弃一个观察值,例如4,按位置采样会产生不同的结果,因为现在5到10个所有移动的位置 .另一种方法是使用散列函数将ID映射到一些伪随机数,然后对这些数字的mod进行采样 . 此样本更稳定,因为分配现在由每个观察的散列决定,而不是由其相对位置决定 .
例如:
[1] 9999
[1] 5000
[1] 2653
[1] 5057
[1] 5057
样本大小不完全是5000,因为赋值是概率性的,但由于大数定律,它在大样本中不应该成为问题 .
另见:http://blog.richardweiss.org/2016/12/25/hash-splits.html和https://crypto.stackexchange.com/questions/20742/statistical-properties-of-hash-functions-when-calculating-modulo
有一种非常简单的方法可以使用行索引和列的R索引来选择多行 . 这使您可以在给定多行的情况下清理分割数据集 - 比如说您的数据的前80% .
在R中,所有行和列都被编入索引,因此DataSetName [1,1]是分配给第一列和“DataSetName”的第一行的值 . 我可以使用[,x]和[,x]列选择行
例如:如果我有一个方便地命名为“data”且100行的数据集,我可以使用查看前80行
以同样的方式,我可以使用以下选择这些行并对它们进行子集化
现在我将我的数据分成两部分而不可能重新采样 . 快捷方便 .