【问题标题】:Using cummean with group_by and ignoring NAs将 cummean 与 group_by 一起使用并忽略 NA
【发布时间】:2018-04-18 18:20:42
【问题描述】:
df <- data.frame(category=c("cat1","cat1","cat2","cat1","cat2","cat2","cat1","cat2"),
                 value=c(NA,2,3,4,5,NA,7,8))

我想在上述数据框中添加一个新列,该列采用value 列的累积平均值,不考虑 NA。 dplyr 可以做到这一点吗?我试过了

df <- df %>% group_by(category) %>% mutate(new_col=cummean(value))

cummean 只是不知道如何处理 NA。

编辑:我不想将 NA 计为 0。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    对于cummean 调用,您可以使用ifelseNAs 视为0

    library(dplyr)
    
    df <- data.frame(category=c("cat1","cat1","cat2","cat1","cat2","cat2","cat1","cat2"),
                     value=c(NA,2,3,4,5,NA,7,8))
    
    df %>%
      group_by(category) %>%
      mutate(new_col = cummean(ifelse(is.na(value), 0, value)))
    

    输出:

    # A tibble: 8 x 3
    # Groups:   category [2]
      category value new_col
      <fct>    <dbl>   <dbl>
    1 cat1       NA     0.  
    2 cat1        2.    1.00
    3 cat2        3.    3.00
    4 cat1        4.    2.00
    5 cat2        5.    4.00
    6 cat2       NA     2.67
    7 cat1        7.    3.25
    8 cat2        8.    4.00
    

    编辑:现在我看到这与忽略 NA 不同。

    试试这个吧。我按指定值是否为 NA 的列分组,这意味着 cummean 可以运行而不会遇到任何 NA:

    library(dplyr)
    
    df <- data.frame(category=c("cat1","cat1","cat2","cat1","cat2","cat2","cat1","cat2"),
                     value=c(NA,2,3,4,5,NA,7,8))
    
    df %>%
      group_by(category, isna = is.na(value)) %>%
      mutate(new_col = ifelse(isna, NA, cummean(value)))
    

    输出:

    # A tibble: 8 x 4
    # Groups:   category, isna [4]
      category value isna  new_col
      <fct>    <dbl> <lgl>   <dbl>
    1 cat1       NA  TRUE    NA   
    2 cat1        2. FALSE    2.00
    3 cat2        3. FALSE    3.00
    4 cat1        4. FALSE    3.00
    5 cat2        5. FALSE    4.00
    6 cat2       NA  TRUE    NA   
    7 cat1        7. FALSE    4.33
    8 cat2        8. FALSE    5.33
    

    【讨论】:

    • 在此方法中NA 在计算mean 时不会被忽略。也许OP 想在计算平均值时忽略NA 值。
    • 谢谢!我意识到我还需要它来计算不包括当前观察的累积平均值 - 不幸的是,使用ifelse(isna, NA, cummean(lag(value))) 不起作用,因为lag 会生成 NA。我已将其作为单独的问题发布stackoverflow.com/questions/49909523/…
    【解决方案2】:

    一个选项是在计算cummean 之前删除值。在此方法中,具有NA 值的行将不计入cummean 计算。不确定 OP 是否想在计算中将 NA 值视为 0

    df %>% mutate(rn = row_number()) %>%
      filter(!is.na(value)) %>%
      group_by(category) %>%
      mutate(new_col = cummean(value)) %>%
      ungroup() %>% 
      right_join(mutate(df, rn = row_number()), by="rn") %>%
      select(category = category.y, value = value.y, new_col) %>%
      as.data.frame()
    #    category value  new_col
    # 1     cat1    NA       NA
    # 2     cat1     2 2.000000
    # 3     cat2     3 3.000000
    # 4     cat1     4 3.000000
    # 5     cat2     5 4.000000
    # 6     cat2    NA       NA
    # 7     cat1     7 4.333333
    # 8     cat2     8 5.333333
    

    【讨论】:

      【解决方案3】:

      我需要类似的东西,但不能用0 替换NAs。所以我创建了这个简单的函数,它适用于dplyr。希望这会有所帮助。

      cummean.na <- function(x, na.rm = T)
      {
        # x = c(NA, seq(1, 10, 1)); na.rm = T
        n <- length(x)
        op <- rep(NA, n)
        for(i in 1:n) {op[i] <- ifelse(is.na(x[i]), NA, mean(x[1:i], na.rm = !!na.rm))}
        rm(x, na.rm, n, i)
        return(op)
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-25
        • 1970-01-01
        • 2014-06-04
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 2021-08-28
        • 2016-06-23
        • 2021-06-17
        相关资源
        最近更新 更多