使用 sample 函数进行过采样
Oversampling with sample function
我想创建一个 mtcars
数据集,其中所有圆柱体都有 100 个观测值。为此,我会抽样替换现有的观察结果。
我试过以下代码,由于某种原因,它没有产生 300 个观察结果。
library(data.table)
mtcars <- data.table(mtcars)
resampling <- list()
set.seed(3)
cyl <- sort(unique(as.character(mtcars$cyl)))
for (i in 1:length(cyl)){
min_obs_cyl <- 100
dat_cyl <- mtcars[cyl == as.numeric(cyl[i]) ]
resampling[[ cyl[i] ]] <- dat_cyl[sample(1:nrow(dat_cyl),
size = (min_obs_cyl - nrow(mtcars[cyl == cyl[i] ])),
replace = T),]
}
resampling_df <- do.call("rbind", resampling)
mtcars_oversample <- rbind(mtcars, resampling_df)
我得到了 307 个观察结果。任何人都知道我做错了什么?
对于替代解决方案,您可以使用 dplyr
并执行:
library(dplyr)
mtcars %>%
group_by(cyl) %>%
do(sampled = sample_n(., size = 100, replace = TRUE)) %>%
select(-cyl) %>%
unnest()
这是使用 dplyr::slice
的另一种方法
mtcars %>%
group_by(cyl) %>%
slice(sample(n(), 100, replace = T)) %>%
ungroup()
我认为在这种情况下,您可以使用 data.table
的 by=
功能在组内进行抽样。 sample
来自每个 cyl
组中的 .I
行计数器,然后使用此行标识符对原始集合中的行进行子select:
mtcars[mtcars[, sample(.I, 100, replace=TRUE), by=cyl]$V1,]
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
# 2: 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
# 3: 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
# 4: 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
# 5: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# ---
#296: 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
#297: 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
#298: 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
#299: 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
#300: 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
如果您需要为每个组指定不同的计数,这里有一个选项。特殊的 .BY
对象将 by=
参数的值存储为列表。
grpcnt <- setNames(c(50,100,70), unique(mtcars$cyl))
# 6 4 8
# 50 100 70
mtcars[mtcars[, sample(.I, grpcnt[as.character(.BY[[1]])], replace=TRUE), by=cyl]$V1]
我想创建一个 mtcars
数据集,其中所有圆柱体都有 100 个观测值。为此,我会抽样替换现有的观察结果。
我试过以下代码,由于某种原因,它没有产生 300 个观察结果。
library(data.table)
mtcars <- data.table(mtcars)
resampling <- list()
set.seed(3)
cyl <- sort(unique(as.character(mtcars$cyl)))
for (i in 1:length(cyl)){
min_obs_cyl <- 100
dat_cyl <- mtcars[cyl == as.numeric(cyl[i]) ]
resampling[[ cyl[i] ]] <- dat_cyl[sample(1:nrow(dat_cyl),
size = (min_obs_cyl - nrow(mtcars[cyl == cyl[i] ])),
replace = T),]
}
resampling_df <- do.call("rbind", resampling)
mtcars_oversample <- rbind(mtcars, resampling_df)
我得到了 307 个观察结果。任何人都知道我做错了什么?
对于替代解决方案,您可以使用 dplyr
并执行:
library(dplyr)
mtcars %>%
group_by(cyl) %>%
do(sampled = sample_n(., size = 100, replace = TRUE)) %>%
select(-cyl) %>%
unnest()
这是使用 dplyr::slice
mtcars %>%
group_by(cyl) %>%
slice(sample(n(), 100, replace = T)) %>%
ungroup()
我认为在这种情况下,您可以使用 data.table
的 by=
功能在组内进行抽样。 sample
来自每个 cyl
组中的 .I
行计数器,然后使用此行标识符对原始集合中的行进行子select:
mtcars[mtcars[, sample(.I, 100, replace=TRUE), by=cyl]$V1,]
# mpg cyl disp hp drat wt qsec vs am gear carb
# 1: 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
# 2: 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
# 3: 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
# 4: 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
# 5: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# ---
#296: 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
#297: 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
#298: 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
#299: 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
#300: 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
如果您需要为每个组指定不同的计数,这里有一个选项。特殊的 .BY
对象将 by=
参数的值存储为列表。
grpcnt <- setNames(c(50,100,70), unique(mtcars$cyl))
# 6 4 8
# 50 100 70
mtcars[mtcars[, sample(.I, grpcnt[as.character(.BY[[1]])], replace=TRUE), by=cyl]$V1]