【问题标题】:Substitute NAs by value present in grouped variables用分组变量中的值替换 NA
【发布时间】:2019-02-03 04:58:18
【问题描述】:

假数据

fruit <- c("Orange", "Banana", "Orange", "Banana")
flavour <- c("Bitter", NA, NA, "Sweet")
geo <- c(NA, NA, NA, "France")
value <- c(1, NA, NA, 4)
dd <- data.frame(fruit, flavour, geo, value)
rm(fruit, flavour, geo, value)

我想按“水果”对数据集进行分组并替换缺失值 在分组数据中存在值的所有变量中。

期望的输出

fruit <- c("Orange", "Banana", "Orange", "Banana")
flavour <- c("Bitter", "Sweet", "Bitter", "Sweet")
geo <- c(NA, "France", NA, "France")
value <- c(1, 4, 1, 4)
dd2 <- data.frame(fruit, flavour, geo, value)
rm(fruit, flavour, geo, value)

代码尝试

tt <- dd %>%
  group_by(fruit) %>%
  summarise_all()

【问题讨论】:

  • 基本 R 选项:dd$flavour &lt;- with(dd, ave(flavour, fruit, FUN = function(x) x[!is.na(x)])).
  • 如果一个组中有多个非NA值,你想做什么?
  • 这不太可能发生在我的数据中。但是,如果变量是数字,我想做平均,如果它是字符,我理想地连接可能的值。感谢 cmets。

标签: r dplyr na


【解决方案1】:

我们在group_by 之后需要mutate_allsummarise/summarise_all 用于从多行中获取单行)。使用zoo 中的na.locf 用每列的相邻非NA 元素填充NA 元素

library(zoo)
library(dplyr)
dd %>% 
  group_by(fruit) %>% 
  mutate_all(funs(na.locf(na.locf(., na.rm =  FALSE), 
                 fromLast = TRUE, na.rm = FALSE)))
# A tibble: 4 x 4
# Groups:   fruit [2]
#  fruit  flavour geo    value
#  <fct>  <fct>   <fct>  <dbl>
#1 Orange Bitter  <NA>       1
#2 Banana Sweet   France     4
#3 Orange Bitter  <NA>       1
#4 Banana Sweet   France     4

【讨论】:

  • 感谢您的回答!但是,我收到一个错误,因为我的一个条目只有 NA。查看修改。
  • @user3262756 更新了帖子。希望对你有帮助
  • 该解决方案有效,但我收到此警告消息:警告消息:1:在 na.locf.default(., flavor, fromLast = TRUE, na.rm = FALSE) 中:na.locf。默认值:rev= 已弃用。请改用 fromLast=。
  • @user3262756 这看起来像是一个友好的警告。
  • @user3262756 现在,您可以检查警告是否存在。我认为funs 中的%&gt;% 触发了警告,尽管它对最终结果没有太大影响
【解决方案2】:

我创建了一个函数来做到这一点。它依赖于 dplyr::coalesce。 只有当组中的所有值都相等时,它才会填充这些值。还可以指定已知值的最小值(n 或百分比),以防止单个值填充组中的所有值

library(dplyr)
fill_missing <- function (x, min_known_n = NULL, min_known_p = NULL) {
    if (NA %in% x) {
        y <- na.omit(x)
        y_n_distinct <- length(unique(y))
        if (!is.null(min_known_n)) {
            known_n <- length(y)
            if (known_n < min_known_n) {
                return(x)
            }
        }
        if (!is.null(min_known_p)) {
            known_p <- length(y)/length(x)
            if (known_p < min_known_p) {
                return(x)
            }
        }
        if (y_n_distinct == 1) {
            x <- dplyr::coalesce(x, y[1])
        }

    }
    return(x)
}

dd %>% group_by(fruit) %>% 
    mutate_all(fill_missing)

【讨论】:

  • 非常好的解决方案!非常感谢!
  • 我已将函数放入 fillr 包中,以便使用函数 fill_missing_strict 执行此操作。它在 CRAN jelger12.github.io/fillr
猜你喜欢
  • 1970-01-01
  • 2019-03-25
  • 2020-09-01
  • 2014-06-28
  • 1970-01-01
  • 2020-03-24
  • 2019-03-22
  • 2020-07-15
相关资源
最近更新 更多