为什么 R 'sample' 某些列比其他列多?

Why does R 'sample' some columns more than others?

我正在测试缺失数据对回归分析的影响。因此,使用模拟数据集,我想从一组指定的列中随机删除一部分观察值(不是整行)。我正在使用 'sample' 来执行此操作。不幸的是,这使得某些列的缺失值比其他列多得多。请参阅下面的示例:

#Data frame with 5 columns, 10 rows
DF = data.frame(A = paste(letters[1:10]),B = rnorm(10, 1, 10), C = rnorm(10, 1, 10), D = rnorm(10, 1, 10), E = rnorm(10,1,10))

#Function to randomly delete a proportion (ProportionRemove) of records per column, for a designated set of columns (ColumnStart - ColumnEnd)
RandomSample = function(DataFrame,ColumnStart, ColumnEnd,ProportionRemove){
  #ci is the opposite of the proportion
  ci = 1-ProportionRemove
  Missing = sapply(DataFrame[(ColumnStart:ColumnEnd)], function(x) x[sample(c(TRUE, NA), prob = c(ci,ProportionRemove), size = length(DataFrame), replace = TRUE)])}

#Randomly sample column 2 - 5 within DF, deleting 80% of the observation per column
Test = RandomSample(DF, 2, 5, 0.8)

我知道这有一个随机因素,但在 10 次试验中(10*4 = 40 列),其中 17 列没有数据,而在一次试验中,一列仍然有 6 条记录(而不是比预期的 ~2) - 见下文。

       B         C         D  E
 [1,] NA 24.004402  7.201558 NA
 [2,] NA        NA        NA NA
 [3,] NA  4.029659        NA NA
 [4,] NA        NA        NA NA
 [5,] NA 29.377632        NA NA
 [6,] NA  3.340918 -2.131747 NA
 [7,] NA        NA        NA NA
 [8,] NA 15.967318        NA NA
 [9,] NA        NA        NA NA
[10,] NA -8.078221        NA NA 

总而言之,我想在每列中用 NA 替换一定比例的观察值。

非常感谢任何帮助!!!

这对我来说很有意义。正如@Frank 所建议的(在 since-deleted 评论中......*叹息*),"randomness" 可以给你真正的 non-random-looking 结果(Dilbert: Tour of Accounting, 2001-10-25)。

如果您想要保证比率的随机样本,试试这个:

guaranteedSampling <- function(DataFrame, ProportionRemove) {
  n <- max(1L, floor(nrow(DataFrame) * ProportionRemove))
  inds <- replicate(ncol(DataFrame), sample(nrow(DataFrame), size=n), simplify=FALSE)
  DataFrame[] <- mapply(`[<-`, DataFrame, inds, MoreArgs=list(NA), SIMPLIFY=FALSE)
  DataFrame
}

set.seed(2)
guaranteedSampling(DF[2:5], 0.8)
#           B         C         D        E
# 1        NA        NA        NA       NA
# 2        NA        NA        NA       NA
# 3        NA        NA        NA       NA
# 4  6.792463 10.582938        NA       NA
# 5        NA        NA -0.612816       NA
# 6        NA -2.278758        NA       NA
# 7        NA        NA        NA 2.245884
# 8        NA        NA        NA 5.993387
# 9  7.863310        NA  9.042127       NA
# 10       NA        NA        NA       NA

根据@joran 的评论,您想要 nrow(DataFrame)length(x)

您的示例中的具体影响是您正在生成一个包含 5 个元素的向量(因为 DF 有 5 个变量)每个元素成为 NA 的概率为 0.8,成为 [=19 的概率为 0.2 =].

然后这个语句(这是 sapply 对您指定的每一列所做的,在这种情况下我只应用于 DF$B):

DF$B[sample(c(TRUE, NA), prob=c(0.2, 0.8), size = 5, replace=TRUE)]

做一些外行人不是很明显的事情*。这个:

sample(c(TRUE, NA), prob=c(0.2, 0.8), size = 5, replace=TRUE)

给出一个逻辑向量,当它用于提取向量的元素时静默回收。所以假设你最终得到:

NA TRUE NA TRUE NA

当你子集 DF$B 你最终得到这个:

DF$B[c(NA, TRUE, NA, TRUE, NA, NA, TRUE, NA, TRUE, NA)]

请注意在您的示例中,前 5 个数字始终遵循与后 5 个数字相同的模式。这解释了为什么这么多列最终都是 NA,因为有 0.32768 的概率从 5 NA 中得到 5 个,它被回收到整个列。

您的代码的另一个问题是该函数实际上没有做任何有用的事情,因为您没有指定任何 return 值。此处已更正和清理并使用 http://adv-r.had.co.nz/Style.html:

random_sample <-  function(x, col_start, col_end, p) {
  sapply(x[col_start:col_end], 
         function(y) y[sample(c(TRUE, NA), prob = c(1-p, p), size = length(y), replace = TRUE)])
}

*这里的外行包括我!在看到这个问题之前,我不知道逻辑向量在用于提取时会被回收。