在R

时间:2015-04-22 22:38:42

标签: r random-sample replicate

我正在努力创建一个矢量化的功能解决方案,这将允许我复制分层随机抽样而无需在多次迭代中进行替换。我可以在没有替换一次的情况下进行采样,然后从数据集中删除这些行,然后从非采样观察中重复该过程。不幸的是,我需要多次这样做,这使得这个手动选项变得不可能。

我尝试过使用replicate()函数,但是我只能在每次传递时都没有替换样本。它将选定的样本放回数据集中,以便进行下一次抽样。

使用下面的代码,我希望该函数能够创建30个新数据集,这些数据集由3个唯一(以前未采样的)行组成,每个行来自“一个”和“零”集。因此,每个新数据集将具有6个总观测值(3-1和3-0)并且被命名为独特的(即“new_dat1”,“new_dat2”......“new_dat30”)。

如果可能的话,我希望在不使用for循环的情况下实现所有这一切,因此首选“apply”系列中的某些内容。

set.seed(123)
dat <- data.frame(Outcome = round(runif(160, 0, 1)))
cust <- data.frame(Cust = rep(c("ABC", "DEF", "GHI"), c(45, 80, 35)))
dat <- cbind(cust, dat)

one <- subset(dat, Outcome == 1)
zero <- subset(dat, Outcome == 0)


# Manual option which is not sufficient    
################################################
# sample 1's and remove choosen obs from "one" dataset
set.seed(123)
index <- sample(1:nrow(one), 3, replace = FALSE)
new_dat1 <- one[index, ]
unused_one <- one[-index, ]

# sample 0's and remove choosen obs from "zero" dataset
set.seed(123)
index <- sample(1:nrow(zero), 3, replace = FALSE)
unused_zero <- zero[-index, ]

# combine the 3-1 and 3-0 samples into the first of 30 "new_datn" sets
new_dat1 <- rbind(new_dat1, zero[index, ])

# repeat, now sampling from "unused_one" and "unused_zero" to create "new_dat2" - "new_dat30"
################################################


# Failed attempt using the replicate() function
################################################
set.seed(123)
one_sample <- replicate(30, one[sample(nrow(one), 3, replace = FALSE), ], simplify = FALSE)
zero_sample <- replicate(30, zero[sample(nrow(zero), 3, replace = FALSE), ], simplify = FALSE)

使这个更加复杂的事实是,我在“数据”集中的0和1总观察数量会不时变化,所以我可能总是有剩余要处理。因此,该函数必须能够为每个“new_dat”采样3,直到它遇到最终集的余数,无论值是什么,都可以进入最终的“new_dat”。

即使我能弄清楚如何在矢量化函数中解决采样问题,我也真的不知道该函数是否创建新数据集并对其进行适当命名。

如果有人能给我一些帮助,我将非常感激。感谢您抽出宝贵时间阅读我的帖子。

1 个答案:

答案 0 :(得分:1)

如果我理解你想要什么,这是一个解决方案。

首先只是对整个矢量进行采样,也就是说,您只是对行号进行随机排序:

sample_rows  <- sample(nrow(one))

然后为每个随机分布的行分配一个样本组(按组分组3个元素)。由于元素的数量可能不能被3整除,因此扩展向量的长度使其具有与行数相同的长度。现在用下一组填充NA(我认为这就是你对“最后一组的余数”的意思):

sample_group <- rep(1:(length(sample_rows)%/% 3), each = 3)
length(sample_group) <- length(sample_rows)
sample_group[is.na(sample_group)] <- max(sample_group, na.rm = TRUE) + 1

所以现在你有24个3个样本和2个样本,没有替换:

samples <- data.frame(sample_rows, sample_group)

head(samples)
  sample_rows sample_group
1          12            1
2           6            1
3          41            1
4          35            2
5          71            2
6          62            2

tail(samples)
   sample_rows sample_group
69          69           23
70          53           24
71          32           24
72          27           24
73          18           25
74          65           25

我为“one”的矢量做了这个,但你可以很容易地复制零矢量并将它们组合起来。

PS:您可以使用split()lapply()从data.frame中提取行。例如:

new_dat <- lapply(split(samples$sample_rows, samples$sample_group), function(x) one[x,])

所以new_dat是一个包含全部25 data.frames的列表。例如:

new_dat[[8]] # gives you the eigth data.frame

或者:

new_dat[[25]] # gives you the last data.frame