【问题标题】:New dplyr version 1.0.6 (or couldve been sooner) seems to misuse plyr . dot in dplyr mutate across新的 dplyr 版本 1.0.6(或可能更早)似乎滥用 plyr 。 dplyr 中的点突变
【发布时间】:2021-08-25 13:13:31
【问题描述】:

在我的 R 从 4.0 版更新到 4.1 版之前,我的以下代码运行良好 请注意,这都是我为正在开发的软件编写的辅助函数的一部分,并且我已经相应地替换了一些东西。没有上下文,这个功能似乎毫无意义,请不要把注意力集中在代码在这里试图完成的事情上。

input1 <- data.frame(a = as.numeric(c(0, NA, 0, 0, NA)),
                       b = as.factor(c("f", "f", NA, "f", NA)),
                       stringsAsFactors = FALSE)
input2 <- data.frame(a = as.numeric(1),
                     b = factor(c("m")),
                     c = factor(c("married")),
                     d = factor(c("AZ")),
                     e = as.character(0),
                     f = as.integer(59),
                     g = as.Date("2021-02-14"),
                     stringsAsFactors = FALSE
                     )

input2 <- input2 %>% dplyr::select( tidyselect::all_of( colnames(fake_data_) ) )

# error occurs here, in the second mutate
input1 %>%
  dplyr::mutate(dplyr::across(.fns = as.character)) %>%
  dplyr::mutate(dplyr::across( .cols = tidyselect::everything(),
                               .fns  = ~eval(parse(text = paste0( "as.",
                                                                  class( input2[[ dplyr::cur_column() ]]),
                                                                  "(.)")))
                               ))

我收到错误Error: Problem with `mutate()` input `..1`. i `..1 = dplyr::across(...)`. x 'list' object cannot be coerced to type 'double'

有人可以帮忙吗,在此先感谢!

【问题讨论】:

    标签: r dynamic dplyr across


    【解决方案1】:

    好的,所以我做了一些挖掘,发现这行得通

    input1 %>%
      dplyr::mutate(dplyr::across(.fns = as.character)) %>%
      dplyr::mutate(dplyr::across( .cols = tidyselect::everything(),
                                   .fns  = function(x) eval(parse(text = paste0( "as.",
                                                                      class( input2[[ dplyr::cur_column() ]]),
                                                                      "(x)")))
                                   ))
    

    现在我的问题是,为什么 . 和 purrr 风格的函数 ~ 不起作用?更好的是,当看到这个. 时,cross 会尝试做什么,这个. 通常是如何使用的?我一直在为此苦苦挣扎,永远找不到它的文档

    【讨论】:

      【解决方案2】:

      对于~purrr,您可以轻松了解它们的工作原理

      library(rlang)
      
      fun <- as_function(~.x + 1)
      
      fun
      #> <lambda>
      #> function (..., .x = ..1, .y = ..2, . = ..1) 
      #> .x + 1
      #> attr(,"class")
      #> [1] "rlang_lambda_function" "function"
      

      这里我们看到它将创建一个函数,并将.x 的默认值映射到第一个参数,.y 的默认值映射到第二个参数,. 的默认值映射到第一个参数为嗯。

      您遇到的问题可能是由于dplyr 的评估掩码和对语言的计算。

      你正在表达你的功能如下

       fun2 <- as_function(~eval(parse(text = paste0( "as.", 
         class( input2[[ dplyr::cur_column() ]]),
         "(.)"))))
      

      并期望使用purrr 样式函数,但实际发生的情况是每次对列的调用都在评估之前将其表达式替换为列名。由于"(.)" 是一个字符,因此不会发生替换,而是尝试使用magrittr. 前缀。

      如果您执行以下操作,您可以了解正在发生的事情

      input1 %>%
        dplyr::mutate(dplyr::across(.fns = ~{browser(); as.character(.)}))
      
      

      如果没有出现浏览器控件,请在控制台中输入n 以查看下一步,它应该是as.character(a),而不是as.character(.)

      (注意:输入Q退出调试浏览器)

      以下应该也会产生您想要的结果:

      input1 %>%
        dplyr::mutate(dplyr::across(.fns = as.character)) %>%
        dplyr::mutate(dplyr::across( .cols = tidyselect::everything(),
                                     .fns  = ~ do.call(paste0("as.",class(input2[[cur_column()]])), list(.))))
        ))
      

      至于为什么在不同的版本中会出现这种情况,我不知道。我电脑上的 3.6.3 版本产生的结果与 4.1 类似。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-08
        • 2020-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-05
        相关资源
        最近更新 更多