我正在测试缺失数据对回归分析的影响。因此,使用模拟数据集,我想从指定的一组列中随机删除一部分观察值(而不是整行)。我正在使用'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替换观察的比例。
非常感谢任何帮助!!!
答案 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)])
}
*在这种情况下,不知情的人包括我!我不知道逻辑矢量在用于提取时会被回收,直到看到这个问题。