【问题标题】:Using a function within a function coded in dplyr在 dplyr 编码的函数中使用函数
【发布时间】:2018-02-24 12:33:43
【问题描述】:

我想在一个函数中使用一个函数,其列名编码为dplyr,如下所示,这会引发以下错误:

grouped_df_impl(data, unname(vars), drop) 中的错误:列 G 是 未知

代码:

# rm(list = ls())

set.seed(12345)
Y  <- rnorm(10)
Env <- paste0("E", rep(1:2, each = 5))
Gen <- paste0("G", rep(1:5, times = 2))
df1 <- data.frame(Y, Env, Gen)

fn1 <- function(.data, .gen, .env, .y){

  Y   <- deparse(substitute(.y))
  G   <- deparse(substitute(.gen))
  E   <- deparse(substitute(.env))

  ge_means <-
    .data %>%
    dplyr::group_by(!!rlang::sym(G), !!rlang::sym(E)) %>%
    dplyr::summarize(Mean = mean(!!rlang::sym(Y)))

  return(list(
    ge_means = ge_means
    ))
}

fn1(
    .data = df1
  , .gen  = Gen
  , .env  = Env
  , .y    = Y
)


fn2 <- function(.data, .gen, .env, .y){

  Y   <- deparse(substitute(.y))
  G   <- deparse(substitute(.gen))
  E   <- deparse(substitute(.env))

  ge_means1 <- 
      fn1(
          .data = .data
        , .gen  = G
        , .env  = E
        , .y    = Y
      )$ge_mean

  return(list(
    ge_means1 = ge_means1
  ))
}


fn2(
    .data = df1
  , .gen  = Gen
  , .env  = Een
  , .y    = Y
)

【问题讨论】:

  • 请不要发布像rm(...) 这样会破坏读者工作空间的破坏性命令。
  • 提醒您,我们希望您不要添加多少您会感谢所有帖子的答案。在普通谈话中这是一种礼貌,但在adding to editors' workloads 时,则恰恰相反。以后请不要再做吗?
  • 感谢您使您最近提出的问题更加简洁。这是一个明确的改进,并将减少您的帖子所需的工作量。我还将提供以下建议:backtick device 添加了适用于代码、日志、错误和控制台 IO 的简短示例的内联代码格式。它带有一定的语义,不是一般的荧光笔。
  • 因此,如果您想谈论通用软件、服务和编程语言,这些不需要需要代码格式化,因为它们的名称(Python、Ubuntu、GitHub 等)是不是自己的代码。它们本质上是专有名词,因此只需要以正确的大小写(通常是首字母大写)呈现。库处于中间地带,因为它们的名称被输入到包管理器中,因此它们可以被视为 IO。但是,如果有疑问,请不要添加格式 - 这会造成混淆且不必要。

标签: r function debugging dplyr


【解决方案1】:

我们可以使用enquo 代替deparse/substitute,然后使用sym 转换回符号

fn1 <- function(.data, .gen, .env, .y){

  Y   <- enquo(.y)
  G   <- enquo(.gen)
  E   <- enquo(.env)

  ge_means <-
    .data %>%
    dplyr::group_by(!! G, !! E) %>%
    dplyr::summarize(Mean = mean(!! Y))

  return(list(
    ge_means = ge_means
    ))
}

fn1(
    .data = df1
  , .gen  = Gen
  , .env  = Env
  , .y    = Y
)

-输出

#$ge_means
# A tibble: 10 x 3
# Groups: Gen [?]
#   Gen    Env      Mean
#   <fctr> <fctr>  <dbl>
# 1 G1     E1      0.586
# 2 G1     E2     -1.82 
# 3 G2     E1      0.709
# 4 G2     E2      0.630
# 5 G3     E1     -0.109
# 6 G3     E2     -0.276
# 7 G4     E1     -0.453
# 8 G4     E2     -0.284
# 9 G5     E1      0.606
#10 G5     E2     -0.919

对于“fn2”,将“.y”、“.gen”、“.env”转换为使用enquo 的quosure,然后使用!!评估“fn1”的参数

fn2 <- function(.data, .gen, .env, .y){
      Y   <- enquo(.y)
      G   <- enquo(.gen)
      E   <- enquo(.env)

     ge_means1 <-  fn1(
          .data, 
         .gen = !! G,  
         .env = !! E,   
         .y = !! Y    
      )$ge_mean

      return(list(
    ge_means1 = ge_means1
  ))

}


fn2(
    .data = df1,
   .gen  = Gen,
   .env  = Env,
   .y    = Y
)

-输出

#$ge_means1
# A tibble: 10 x 3
# Groups: Gen [?]
#   Gen    Env      Mean
#   <fctr> <fctr>  <dbl>
# 1 G1     E1      0.586
# 2 G1     E2     -1.82 
# 3 G2     E1      0.709
# 4 G2     E2      0.630
# 5 G3     E1     -0.109
# 6 G3     E2     -0.276
# 7 G4     E1     -0.453
# 8 G4     E2     -0.284
# 9 G5     E1      0.606
#10 G5     E2     -0.919

【讨论】:

    【解决方案2】:

    我们可以像这样使用...

    fn2 <- function(...) list(ge_means1 = fn1(...)$ge_mean)
    
    fn2(df1, Gen, Env, Y)
    

    给予:

    $ge_means1
    # A tibble: 10 x 3
    # Groups: Gen [?]
       Gen    Env      Mean
       <fctr> <fctr>  <dbl>
     1 G1     E1      0.586
     2 G1     E2     -1.82 
     3 G2     E1      0.709
     4 G2     E2      0.630
     5 G3     E1     -0.109
     6 G3     E2     -0.276
     7 G4     E1     -0.453
     8 G4     E2     -0.284
     9 G5     E1      0.606
    10 G5     E2     -0.919
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多