【问题标题】:Recode multiple columns using dplyr使用 dplyr 重新编码多个列
【发布时间】:2018-05-11 08:10:00
【问题描述】:

我有一个数据框,我在其中重新编码了几列,以便将 999 设置为 NA

dfB <-dfA %>%
  mutate(adhere = if_else(adhere==999, as.numeric(NA), adhere)) %>%
  mutate(engage = if_else(engage==999, as.numeric(NA), engage)) %>%
  mutate(quality = if_else(quality==999, as.numeric(NA), quality)) %>%
  mutate(undrstnd = if_else(undrstnd==999, as.numeric(NA), undrstnd)) %>%
  mutate(sesspart = if_else(sesspart==999, as.numeric(NA), sesspart)) %>%
  mutate(attended = if_else(attended>=9, as.integer(NA), attended))

我想使用 mutate_at() 和一系列列和 recode() 而不是 if_else(),但我不知道如何给它条件。我认为 999 = NA 基于一些 mutate_all 示例 - 但我还需要 NA 来匹配 .x 的类型,我不确定如何让它成为类型敏感的

我试过了:

y <- data.frame(y1=c(1,2,999,3,4), y2=c(1L, 2L, 999L, 3L, 4L), y3=c(T,T,F,F,T))
z <- y %>%
    mutate_at( vars(y1:y2), funs(recode(.,`999` = as.numeric(NA))))

但我收到一条警告“视为 NA 的未替换值不兼容。请详细指定替换或提供 .default”,我可以看到它的措辞是针对数字列,而不是针对整数列 y2”

> z
  y1 y2    y3
1  1 NA  TRUE
2  2 NA  TRUE
3 NA NA FALSE
4  3 NA FALSE
5  4 NA  TRUE

【问题讨论】:

    标签: r recode dplyr


    【解决方案1】:

    我认为这与列类型有关。我添加了mutate_if 将所有整数列转换为数字,然后将重新编码值设置为NA_real_。它似乎有效。

    library(dplyr)
    
    y <- data.frame(y1=c(1,2,999,3,4), y2=c(1L, 2L, 999L, 3L, 4L), y3=c(T,T,F,F,T))
    
    z <- y %>%
      mutate_if(is.integer, as.numeric) %>%
      mutate_at(vars(y1:y2), funs(recode(.,`999` = NA_real_)))
    z
    #   y1 y2    y3
    # 1  1  1  TRUE
    # 2  2  2  TRUE
    # 3 NA NA FALSE
    # 4  3  3 FALSE
    # 5  4  4  TRUE
    

    【讨论】:

    • 谢谢,万维网。这确实解决了警告的问题。它强制所有内容为真实,并避免以前整数列的错误类型 NA。我曾考虑过这一点。我还有其他一些代码部分依赖于这些列是整数,我需要在重新编码后将它们重置为整数。我希望有一种方法可以使 NA 值响应每列中的数字类型。
    【解决方案2】:

    现在funs 已在 dplyr 中贬值,这是新的方法:

    z <- y %>%
      mutate_if(is.integer, as.numeric) %>%
      mutate_at(vars(y1:y2), list(~recode(.,`999` = NA_real_)))
    

    funs 替换为list 并在recode 之前插入~

    【讨论】:

    • list() 如果只调用一个函数,则不需要。
    【解决方案3】:

    我无法准确理解您想要完成的任务,所以如果不完全是,请告诉我。


    library(dplyr)
    
    y <- data.frame(y1=c(1,2,999,3,4), y2=c(1L, 2L, 999L, 3L, 4L), y3=c(T,T,F,F,T))
    
    y
    
    #>    y1  y2    y3
    #> 1   1   1  TRUE
    #> 2   2   2  TRUE
    #> 3 999 999 FALSE
    #> 4   3   3 FALSE
    #> 5   4   4  TRUE
    
    z <- y %>%
      mutate_at(vars(y1:y2), ~ifelse(. == 999, NA, .))
    
    z
    
    #>   y1 y2    y3
    #> 1  1  1  TRUE
    #> 2  2  2  TRUE
    #> 3 NA NA FALSE
    #> 4  3  3 FALSE
    #> 5  4  4  TRUE
    

    【讨论】:

    • 感谢evertr。这确实解决了问题。它保留了 if_else() 而不是使用 recode() - 但我可以忍受。我可以使用“。”正如您建议的那样,避免更改为数字。我不清楚为什么它不抱怨 true 的 NA 是错误的类型。在我的原始代码中,我必须使用 as.numeric(NA) 或 as.integer(NA) 以避免错误。你知道为什么这里没有报错吗?
    • 啊,好的。我看到您使用了 ifelse() ,它不像 if_else() 那样检查类型。您知道如何使用 if_else() 来完成此操作,而无需将整个数据框转换为真实数据吗?
    • @D.Bontempo 您可以使用mutate_if(is.numeric, ...),它也匹配整数,这样您就不必选择所有变量(就像在@www 的解决方案中一样,但不进行任何转换) . @everetr 我建议从您的解决方案中删除 as.numeric,因为不需要类型转换。那么这将是值得 +1 的 ;-)
    • @Tino,请参阅我在代码下方的评论。我已经说过,如果需要,可以省略as.numeric。我不知道@D. Bontempo 是否想要转换。
    • @D.Bontempo 请在代码下方查看我的评论。您可以省略 as.numeric 以避免将 y$y2integer 转换为 numeric
    【解决方案4】:

    目前,基于dplyr documentation

    across() 取代了 summarise_at()、summarise_if() 和 summarise_all() 等“范围变体”系列。

    因此,现在建议使用mutateacross

    Chris LeBoasaid,如果你只想将一个烦人的值转换为NA,函数na_if()可能是最好的选择:

    y <- data.frame(y1=c(1,2,999,3,4), y2=c(1L, 2L, 999L, 3L, 4L), y3=c(T,T,F,F,T))
    
    y
       y1  y2    y3
    1   1   1  TRUE
    2   2   2  TRUE
    3 999 999 FALSE
    4   3   3 FALSE
    5   4   4  TRUE
     
    z <- y %>%
        mutate(across(
            y1:y2,
            ~na_if(., 999)
        ))
    
    z
      y1 y2    y3
    1  1  1  TRUE
    2  2  2  TRUE
    3 NA NA FALSE
    4  3  3 FALSE
    5  4  4  TRUE
    

    同样,如果你真的想recode在多个列中的值,你可以按照example from bcarothers

    df1 <- tibble(Q7_1=1:5,
                  Q7_1_TEXT=c("let's","see","grogu","this","week"),
                  Q8_1=6:10,
                  Q8_1_TEXT=rep("grogu",5),
                  Q8_2=11:15,
                  Q8_2_TEXT=c("grogu","is","the","absolute","best"))
    
    df2 <- df1 %>%
        mutate(across(
            starts_with("Q8") & ends_with("TEXT"),
            ~recode(., "grogu"="mando")
        ))
    

    【讨论】:

      【解决方案5】:

      如果您尝试将某些内容重新编码为 NA,na_if() 函数也应该可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多