【问题标题】:Remove "NA" from some specific cells of a data frame. Not all of them从数据框的某些特定单元格中删除“NA”。不是所有的人
【发布时间】:2018-07-13 15:15:13
【问题描述】:

所以我的数据格式如下:

    A   B   C   D   E   F
1   12  NA  NA  28  NA  NA
2   34  NA  NA  29  NA  34
3   98  98  NA  90  NA  67
4   29  34  84  NA  NA  67
5   84  NA  29  89  NA  45
6   87  76  28  28  34  67
7   87  23  28  20  24  34
8   32  98  28  49  23  67
9   43  43  27  39  56  30
10  93  23  85  90  46  65

现在我想要以下格式:

    A   B   C   D   E   F
1   12  98  84  28  34  34
2   34  34  29  29  24  67
3   98  NA  28  90  23  67
4   29  76  28  NA  56  45
5   84  23  28  89  46  67
6   87  98  27  28      34
7   87  43  85  20      67
8   32  23      49      30
9   43          39      65
10  93          90      

然后我想用该列的中位数填充NAs 的左侧。

谁能帮帮我。我对 R 很陌生,很困惑如何实现这一目标。

提前致谢。

【问题讨论】:

  • 这个问题令人困惑。在预期的输出中,NAs 仍然存在。它不是由median 填充的

标签: r dataframe na


【解决方案1】:

这只能使用基础 R 来完成。

我将使用名为 dat1dat2 的数据副本。前者会将所有非缺失值的中位数归入缺失值。后者将在计算中位数之前从向量中删除顶部和底部值。

dat1 <- dat2 <- dat    # Make two copies of the data

dat1[] <- lapply(dat, function(x){
  if(anyNA(x)){
    inx <- which(is.na(x))
    x[inx] <- median(x, na.rm = TRUE)
    c(x[-inx], x[inx])
  } else x
})

dat2[] <- lapply(dat, function(x){
  if(anyNA(x)){
    inx <- which(is.na(x))
    x_tmp <- x[-inx]
    x[inx] <- median(x_tmp[-c(1, length(x_tmp))], na.rm = TRUE)
    c(x[-inx], x[inx])
  } else x
})

dat1
#    A  B  C  D  E  F
#1  12 98 84 28 34 34
#2  34 34 29 29 24 67
#3  98 76 28 90 23 67
#4  29 23 28 89 56 45
#5  84 98 28 28 46 67
#6  87 43 27 20 34 34
#7  87 23 85 49 34 67
#8  32 43 28 39 34 30
#9  43 43 28 90 34 65
#10 93 43 28 39 34 65

dat2
#   A  B  C  D  E  F
#1  12 98 84 28 34 34
#2  34 34 29 29 24 67
#3  98 76 28 90 23 67
#4  29 23 28 89 56 45
#5  84 98 28 28 46 67
#6  87 43 27 20 24 34
#7  87 23 85 49 24 67
#8  32 43 28 39 24 30
#9  43 43 28 90 24 65
#10 93 43 28 39 24 67

编辑。

下面的函数做了上面两个匿名函数所做的事情。所需要的只是将参数设置为适当的值。

请注意,测试会将结果与上述原始结果进行比较。

imputeStat <- function(x, stat = median, remove = c("top", "bottom")){
  if(anyNA(x)){
    inx <- which(is.na(x))
    x_tmp <- x[-inx]
    if("top" %in% remove) inx_rem <- 1
    if("bottom" %in% remove) inx_rem <- c(inx_rem, length(x[-inx]))
    if(is.logical(remove)){
      if(!remove) x[inx] <- median(x, na.rm = TRUE)
    }else{
      x[inx] <- median(x_tmp[-inx_rem], na.rm = TRUE)
    }
    c(x[-inx], x[inx])
  } else x
}

dat3 <- dat
dat3[] <- lapply(dat3, imputeStat, remove = FALSE)
identical(dat1, dat3)
#[1] TRUE

dat4 <- dat
dat4[] <- lapply(dat4, imputeStat)
identical(dat2, dat4)
#[1] TRUE

数据。

dat <- read.table(text = "
    A   B   C   D   E   F
1   12  NA  NA  28  NA  NA
2   34  NA  NA  29  NA  34
3   98  98  NA  90  NA  67
4   29  34  84  NA  NA  67
5   84  NA  29  89  NA  45
6   87  76  28  28  34  67
7   87  23  28  20  24  34
8   32  98  28  49  23  67
9   43  43  27  39  56  30
10  93  23  85  90  46  65
", header = TRUE)

【讨论】:

  • 感谢瑞巴拉达斯。您建议的代码可以解决问题。你能解释一下它在做什么吗?还有一件事情。由于它正在向上移动每列的单元格,所以最后有空格。它也用中位数填充这些空间。有没有可能避免这些?我只想用位于列中数据之间的中位数填充那些空白。不在极端(顶部或底部)。
  • @MiteshSomani 我不明白您所说的“不在极端(顶部或底部)” 是什么意思。在C 列中,删除84(顶部)和85(底部)后的中位数?
  • @MiteshSomani 完成,看看第二个 lapply 是不是你想要的。
  • 非常感谢您的及时回复,让我解释一下。让我们暂时忘记中位数。我们首先需要做的是,如果 NA 位于任何列的开头,那么我们必须删除该 NA 并仅为该列向上移动下面的单元格。这不应该影响其他列。这就是我在原始问题中展示的内容。让我们对这个进行排序,然后我们将继续进行中位数部分。
  • @MiteshSomani 我发布的代码逐列工作,它不会影响其他列。至于移位,你应该马上解决,如果不是,当所有NAs都消失时,你怎么知道要更改哪些列元素?
猜你喜欢
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 2022-01-11
  • 2011-02-08
  • 2019-01-06
  • 2019-01-12
相关资源
最近更新 更多