【问题标题】:R -Finding the columns with only one non-missing value and filling its missing values with that unique non-missing valueR - 查找只有一个非缺失值的列,并用该唯一非缺失值填充其缺失值
【发布时间】:2019-07-18 21:30:09
【问题描述】:

我有一个包含缺失数据 (NA) 的数据框。我想找到只有一个非缺失值的列,然后用该值填充这些列。例如,如果我的原始数据集是这样的:

  df = data.frame(A=c(1,2,NA,NA,1), B=c(NA,NA,3,3,3), C=c(2,5,6,3,6), D = c(NA,1, NA,1,1))

   A  B C  D
1  1 NA 2 NA
2  2 NA 5  1
3 NA  3 6 NA
4 NA  3 3  1
5  1  3 6  1 

我想达到:

   A  B C  D
1  1  3 2  1
2  2  3 5  1
3 NA  3 6  1
4 NA  3 3  1
5  1  3 6  1 

我首先创建了这个函数来做我想做的事:(如果你有更好的选择,请告诉我)

fill_NAs <- function(x){
  x %>% fill(., .direction = "up") %>%
        fill(., .direction = "down")
}

然后我尝试使用 mutate_at 或 mutate_if 函数,但我无法让它工作。我的一些尝试如下:

1)

df= df %>% mutate_if ( ~ length(unique(na.omit(.)))==1, ~ fill_NAs(.))

我收到了这个错误:

mutate_impl(.data, dots) 中的错误:评估错误:不适用 'fill_' 的方法应用于类“c('double', '数字')"

.

2)

df_PMM_imp = df_PMM_imp %>% mutate_at(.,names(select_if(.,length(unique(na.omit(.)))==1)), ~ fill_NAs(.))

我收到了这个错误:

tbl_if_vars(.tbl, .predicate, caller_env() 中的错误, .include_group_vars = TRUE) : 长度(.p) == 长度(tibble_vars) 是 不是真的

总的来说,我似乎无法理解 mutate_if 或 mutate_at 的逻辑,我总是遇到这样的问题。所以我的问题是:

1) 实现我想要的正确语法是什么? 2)为什么会出现上面这些错误,我做错了什么?

非常感谢。

【问题讨论】:

  • 我没有完全理解你想用什么替换你的 NA。

标签: r missing-data dplyr


【解决方案1】:

您可以遍历列,检查不是 NA 的唯一元素的长度,如果列中只包含一个唯一元素,则替换该列中的 NAs。

df[] <- lapply(df, function(x) {
  y <- unique(na.omit(x))
  if(length(y) == 1) {
    x <- y
  } else x
})

结果

df
   A B C D
1  1 3 2 1
2  2 3 5 1
3 NA 3 6 1
4 NA 3 3 1
5  1 3 6 1

【讨论】:

    【解决方案2】:

    嗨@Elif Cansu Akoğuz,

    您可以通过使用for()-loop 来迭代您的数据框并检查每列是否满足您的要求,从而相当容易地实现您的目标:

    for (i in 1:ncol(df)) {
        if (any(is.na(unique(df[i]))) == TRUE & nrow(unique(df[i])) == 2) {
            ...
        }
    }
    

    使用语句any(is.na(unique(df[i]))) 检查列中是否存在NA,使用nrow(unique(df[i])) == 2 检查列是否仅包含两个唯一值。因此,如果一列同时满足这两个语句,您就知道它由 2 个值组成,其中一个位于 NA 中。

    接下来,您想用不是NA 的值替换列中的所有值。为此,您可以使用na.omit() 丢弃NA 值,然后在数据帧长的时间内重复剩余值。 一个问题是这会返回一个列表格式,所以你必须使用unlist()-函数来解决这个问题。

    整个循环最终将如下所示:

    for (i in 1:ncol(df)) {
        if (any(is.na(unique(df[i]))) == TRUE & nrow(unique(df[i])) == 2) {
            df[i] <- unlist(rep(na.omit(unique(df[i])), nrow(df)))
        }
    }
    

    祝你好运!

    【讨论】:

      【解决方案3】:

      dplyr 方式:

      library(dplyr)
      
      df %>% 
        mutate_all(~ case_when(
          n_distinct(.[na.omit(.)]) == 1 ~ first(na.omit(.)),
          TRUE ~ .
          )
        )
      

      输出:

         A B C D
      1  1 3 2 1
      2  2 3 5 1
      3 NA 3 6 1
      4 NA 3 3 1
      5  1 3 6 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-18
        • 2021-09-03
        • 1970-01-01
        • 2019-10-21
        • 1970-01-01
        • 2012-10-25
        相关资源
        最近更新 更多