将随机缺失值的确切比例添加到 data.frame

add exact proportion of random missing values to data.frame

我想在 R 中将随机 NA 添加到 data.frame。到目前为止,我已经研究了这些问题:

R: Randomly insert NAs into dataframe proportionaly

How do I add random NAs into a data frame

add random missing values to a complete data frame (in R)

这里提供了很多解决方案,但我找不到符合这5个条件的解决方案:

有人有想法吗? 我已经尝试编写一个函数来执行此操作(在第一个 link 的回答中),但它不符合第 N°3 和 4 点。 谢谢。

[注意] 确切的比例,当然四舍五入为 +/- 1NA。

这是我在 library(imputeMulti) 上的论文中使用的方法,该论文目前正在 JSS 审稿。这会将 NA 插入到整个数据集的随机百分比中并且可以很好地缩放,它不会 保证 一个确切的数字,因为 n * p * pctNA %% 1 != 0 的情况。

createNAs <- function (x, pctNA = 0.1) {
  n <- nrow(x)
  p <- ncol(x)
  NAloc <- rep(FALSE, n * p)
  NAloc[sample.int(n * p, floor(n * p * pctNA))] <- TRUE
  x[matrix(NAloc, nrow = n, ncol = p)] <- NA
  return(x)
}

显然你应该使用随机种子来实现可重复性,这可以在函数调用之前指定。

这是创建用于比较插补方法的基线数据集的一般策略。我相信这就是你想要的,尽管你的问题(如评论中所述)没有明确说明。

编辑:我认为 x 已经完成。所以,我不确定它将如何处理现有的缺失数据。如果你愿意,你当然可以修改代码,尽管这可能会增加运行时间至少 O(n*p)

一些用户报告说 Alex 的回答没有解决我问题的第 5 条条件。事实上,当在已经包含缺失值的数据帧上添加随机 NA 时,新的有时会落在初始值上,最终比例将介于初始比例和所需比例之间......所以我展开Alex 的函数满足所有 5 个条件:

我修改了他的 createNAs 函数,使其启用 3 个选项之一:

  • option complement:用 NA 补充到所需的 %
  • 选项添加:除了已经存在的那些之外,添加 NA 的百分比
  • 选项 none : 添加 NA 的百分比,不管那些已经存在的

对于选项 1 和 2,该函数将递归地工作,直到达到所需的比例 NA:

createNAs <- function (x, pctNA = 0.0, option = "add"){
  prop.NA = function(x) sum(is.na(x))/prod(dim(x))
  initial.pctNA = prop.NA(x)

  if (  (option =="complement") & (initial.pctNA > pctNA)  ){
    message("The data already had more NA than the target percentage. Returning original data")
    return(x)
  }

  if (  (option == "none") || (initial.pctNA == 0)  ){
    n <- nrow(x)
    p <- ncol(x)
    NAloc <- rep(FALSE, n * p)
    NAloc[sample.int(n * p, floor(n * p * pctNA))] <- TRUE
    x[matrix(NAloc, nrow = n, ncol = p)] <- NA
    return(x)
  } else { # if another option than none:
    target = ifelse(option=="complement", pctNA, pctNA + initial.pctNA)
    while (prop.NA(x) < target) {
      prop.remaining.to.add = target - prop.NA(x)
      x = createNAs(x, prop.remaining.to.add, option = "none")
    }
    return(x)
  }
}