为什么R'对某些列进行采样比其他列更多?

时间:2018-04-10 16:08:47

标签: r random na missing-data sample

我正在测试缺失数据对回归分析的影响。因此,使用模拟数据集,我想从指定的一组列中随机删除一部分观察值(而不是整行)。我正在使用'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 

总之,我想在每一列中用NAs替换观察的比例。

非常感谢任何帮助!!!

2 个答案:

答案 0 :(得分:3)

这对我有意义。正如@Frank建议的那样(在删除的评论中...... *叹气*),"随机性"可以给你真正非随意的结果(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

答案 1 :(得分:2)

继@ joran的评论之后,您要么nrow(DataFrame)还是length(x)

你的例子中的具体影响是你正在生成一个包含5个元素的向量(因为DF有5个变量),每个元素的概率为NA,概率为0. TRUE

然后这个语句(这是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,因为有5个NA中有5个可以回收到整个列的概率为0.32768。

您的代码的另一个问题是该函数实际上没有做任何有用的事情,因为您没有指定任何返回值。在此处使用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)])
}

*在这种情况下,不知情的人包括我!我不知道逻辑矢量在用于提取时会被回收,直到看到这个问题。