如何使用样本函数将数据分割成训练/测试集

我刚开始使用 R,我不知道如何将我的数据集与下面的示例代码结合起来:

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

我有一个数据集,我需要放入一个培训(75%)和测试(25%)集。 我不确定我应该把什么信息输入到 X 和大小里? X 是数据集文件吗? 我有多少样本?

633480 次浏览

有许多实现数据分区的方法。要了解更完整的方法,请查看 caret包中的 createDataPartition函数。

下面是一个简单的例子:

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, ]

如果你输入:

?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% 的测试。

这是几乎相同的代码,但在更漂亮的外观

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

这可以很容易地做到:

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, ]

使用 电子工具软件包:

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

下面是一个创建 相同尺寸子样的 list的函数,它并不完全是您想要的,但可能对其他人有用。在我的例子中,在较小的样本上创建多个分类树来测试过度拟合:

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

我将把“ a”分为 train (70%)和 test (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,]

搞定

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

我的解决办法基本上和迪科阿的一样,只是更容易理解:

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

我会用 dplyr来做这个,使它超级简单。它确实需要在数据集中使用 id 变量,无论如何,这都是一个好主意,不仅用于创建集合,而且用于项目期间的可跟踪性。如果尚未包含,则添加它。

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

在 R 中使用 caTools 包 示例代码如下:-

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

函数 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,]

只是一个更简短和简单的方式使用了不起的 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, ]
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()函数将向数据帧添加一个额外的列‘ split1’,其中2/3行的值为 TRUE,其他行的值为 FALSE。现在,split1为 TRUE 的行将被复制到 train 中,其他行将被复制来测试数据帧。

我的解决方案对行进行洗牌,然后将前75% 的行作为 train,最后25% 作为 test。超级简单!

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)),]

有一种非常简单的方法可以使用 R 索引为行和列选择许多行。这使您可以清晰地分割给定数量行的数据集——比如前80% 的数据。

在 R 中,所有行和列都被索引,因此 DataSetName [1,1]是分配给“ DataSetName”的第一列和第一行的值。我可以使用[ x,]选择行,使用[ ,x ]选择列

例如: 如果我有一个名为“ data”的数据集,它有100行,那么我可以使用

视图(数据[1:80,])

同样,我可以选择这些行,并使用以下方法对它们进行子集:

Train = data [1:80,]

Test = data [81:100,]

现在我把我的数据分成两部分,没有重新采样的可能性。

当心 sample的分裂,如果你寻找可重复的结果。如果您的数据稍有变化,即使使用 set.seed,拆分也会有所不同。例如,假设数据中排序的 ID 列表是1到10之间的所有数字。如果你只是放弃一个观察,比如说4,按地点取样会产生不同的结果,因为现在5到10个地方都移动了。

另一种方法是使用散列函数将 ID 映射到一些伪随机数,然后对这些数的模进行取样。这个示例更加稳定,因为赋值现在是由每个观察值的哈希值决定的,而不是由它的相对位置决定的。

例如:

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 》 并且 < a href = “ https://cryp.stackexchange.com/questions/20742/statistical-properties-of-hash-function-when-Calcul- modulo”> https://crypto.stackexchange.com/questions/20742/statistical-properties-of-hash-functions-when-calculating-modulo

我可以建议使用 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)

假设 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,]
set.seed(123)
llwork<-sample(1:length(mydata),round(0.75*length(mydata),digits=0))
wmydata<-mydata[llwork, ]
tmydata<-mydata[-llwork, ]

在浏览了这里发布的所有不同的方法之后,我没有看到任何人利用 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

scorecard包有一个非常有用的函数,您可以在其中指定比率和种子

library(scorecard)


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

测试和训练数据存储在一个列表中,可以通过调用 dt_list$traindt_list$test来访问

我碰到了这个,它也能帮上忙。

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),]

我们可以把数据分成一个特定的比例,这里是80% 的训练和20% 的测试数据集。

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

我认为这会解决问题:

df = data.frame(read.csv("data.csv"))
# Split the dataset into 80-20
numberOfRows = nrow(df)
bound = as.integer(numberOfRows *0.8)
train=df[1:bound ,2]
test1= df[(bound+1):numberOfRows ,2]

我更喜欢使用 dplyr而不是 mutate的值

set.seed(1)
mutate(x, train = runif(1) < 0.75)

我可以继续使用 dplyr::filter和助手函数,如

data.split <- function(is_train = TRUE) {
set.seed(1)
mutate(x, train = runif(1) < 0.75) %>%
filter(train == is_train)
}

创建一个索引行“ rowid”并使用 anti join 通过 = “ rowid”筛选出来。可以在拆分后使用% >% select (- rowid)删除 rowid 列。

Data <-tibble: : rowid _ to _ column (data)

Set.eed (11081995)

Testdata <-data% >% slice _ sample (prop = 0.2)

Train data <-anti _ join (data,testdata,by = “ rowid”)

我编写了一个函数(我的第一个函数,所以它可能不能很好地工作) ,以便在处理多个数据表并且不想重复代码的情况下更快地完成这个任务。

xtrain <- function(data, proportion, t1, t2){
data <- data %>% rowid_to_column("rowid")
train <- slice_sample(data, prop = proportion)
assign(t1, train, envir = .GlobalEnv)
test <- data %>% anti_join(as.data.frame(train), by = "rowid")
assign(t2, test, envir = .GlobalEnv)
}


xtrain(iris, .80, 'train_set', 'test_set')

您需要加载 dplyr 和 tibble。这需要一个给定的数据集、您希望用于抽样的比例和两个对象名称。该函数创建表,然后将它们作为全局环境中的对象分配。

尝试使用 idx <- sample(2, nrow(data), replace = TRUE, prob = c(0.75, 0.25))和提供的 id 来访问分割数据 training <- data[idx == 1,] testing <- data[idx == 2,]