【问题标题】:change values of several columns based on value in other column with mutate() and across()使用 mutate() 和 cross() 根据其他列中的值更改几列的值
【发布时间】:2021-01-18 16:33:18
【问题描述】:

我想将初始数据帧 (df) 的 a 和 b 列更改为数据帧 df_new 中的列。如果 NAvar 列是 NA,我基本上只想将列 a 和 b 的值设置为“999”。 mutate 和 cross 怎么可能?

df <- data.frame(a =1:5, b = 6:10, NAvar = c(NA, 1, 12, 4, NA))


df %>% 
  dplyr::filter(is.na(NAvar)) %>% 
  select(colnames(df)) %>% 
  mutate(across(c("a", "b"), EqualsTo=999))


df_new <- data.frame(a = c(999, 2:4, 999), b = c(999, 7:9, 999), NAvar = c(NA, 1, 12, 4, NA))

df
df_new

【问题讨论】:

    标签: r dplyr


    【解决方案1】:
    df %>%
      mutate(across(a:b, ~ if_else(is.na(NAvar), 999L, .)))
    #     a   b NAvar
    # 1 999 999    NA
    # 2   2   7     1
    # 3   3   8    12
    # 4   4   9     4
    # 5 999 999    NA
    

    注意999L的使用,副999,一个数字。如果您的真实数据模糊了integernumeric 之间的界限,那么dplyr::if_else 将是有问题的(有充分的理由)。如果您需要避开这一点(也许其他一些计算无意中将a 和/或b 转换为numeric),那么一些选项:

    mutate(across(a:b, ~ if_else(is.na(NAvar), 999L, as.integer(.))))
    mutate(across(a:b, ~ if_else(is.na(NAvar), 999, as.numeric(.))))
    
    ## base::ifelse
    mutate(across(a:b, ~ ifelse(is.na(NAvar), 999, .)))
    

    最后是利用base::ifelse 可以被视为草率这一事实。意识到ifelse(..., 1, "") 可能会返回numericcharacter,这取决于条件,并且事先不知道将返回哪个类的事实是有风险的。虽然integer/numeric 之间的差异风险较小,但如果/当其他表达式需要一个表达式时,它仍然可能是一个问题。

    【讨论】:

      【解决方案2】:

      使用baseR

      df <- data.frame(a =1:5, b = 6:10, NAvar = c(NA, 1, 12, 4, NA))
      cbind(apply(df[1:2], 2, function(x) ifelse(is.na(df$NAvar), 999L, x)), NAvar = df$NAvar)
      #>        a   b NAvar
      #> [1,] 999 999    NA
      #> [2,]   2   7     1
      #> [3,]   3   8    12
      #> [4,]   4   9     4
      #> [5,] 999 999    NA
      

      reprex package (v0.3.0) 于 2021-01-18 创建

      df[1:2] <- lapply(df[1:2], function(x) ifelse(is.na(df$NAvar), 999L, x))
      df
      #>     a   b NAvar
      #> 1 999 999    NA
      #> 2   2   7     1
      #> 3   3   8    12
      #> 4   4   9     4
      #> 5 999 999    NA
      

      reprex package (v0.3.0) 于 2021-01-19 创建

      【讨论】:

      • 两个建议:(1)apply 隐式转换为矩阵;如果所有列都相同class,这不是问题,但它确实减慢了速度。使用lapply(df[1:2], ...) 可以明显更快(使用iris 是3 倍)。 (2)cbind(...)在你有不止一列要“返回”时变得繁重;我推荐df[1:2] &lt;- lapply(df[1:2], ...),因为它固有地更新数据并且不需要更改其他列。
      • 感谢 cmets。他们对我很有帮助。我是编程新手
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-28
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多