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

时间:2016-09-15 14:34:50

标签: r random na missing-data

我想将随机NA添加到R中的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个条件的解决方案:

  • 添加非常随机的NA,而不是按行或列添加相同的数量
  • 处理data.frame(数字,字符,因子,逻辑,ts ..)中可能遇到的每个变量类,因此输出必须与输入data.frame或matrix具有相同的格式。 / LI>
  • 保证输出中NA的确切数量或比例 [note] (许多解决方案导致NA数量较少,因为多个NA在同一位置生成)
  • 计算对大数据集有效吗?
  • 在输入中独立于已存在的NA添加NA的比例/数量。

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

[注意]确切的比例,当然是+/- 1NA。

2 个答案:

答案 0 :(得分:6)

这是我在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)

答案 1 :(得分:0)

一些用户报告说,亚历克斯的答案未解决我问题的第5个条件。确实,当在已经包含缺失值的数据帧上添加随机NA时,新值有时会落在初始值上,而最终比例将介于初始比例和所需比例之间。所以我继续Alex的功能符合所有5个条件:

我修改了他的createNAs函数,以便启用以下三个选项之一:

  • 选项 complement :用NA补充至所需的百分比
  • 选项 add :除了已经存在的NA之外,还添加%的NA
  • 选项:添加%的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)
  }
}