【问题标题】:Rename variable inside function in r using normal evaluation使用正常评估在 r 中重命名函数内部的变量
【发布时间】:2025-12-04 00:55:01
【问题描述】:

假设您有以下函数可以将两种数据框列类型相互比较:

dataframe_test <- function(df1, df2) {

  varnames <- names(df1)[names(df1) %in% names(df2)]
  out <- data.frame(
             df1 = sapply(df1[,varnames], class),
             df2 = sapply(df2[,varnames], class)
             ) 
  out$Test <- ifelse(out$df1 == out$df2, " - ", "FLAG")

  return(out)

  }

下面是使用的函数:

iris2 <- iris

dataframe_test(iris, iris2)

                 df1     df2 Test
Sepal.Length numeric numeric   - 
Sepal.Width  numeric numeric   - 
Petal.Length numeric numeric   - 
Petal.Width  numeric numeric   - 
Species       factor  factor   - 

如何重命名该函数的输出列(在我上面的示例中为 iris、iris2),以使它们与输入数据帧的名称相同?我尝试过的一切都产生了一个或另一个错误。例如,

out <- rename_(out, .dots = setNames(list(df1), new))
colnames(out) <- c(glue::glue("{df1}"), glue::glue("{df2}"), "Flag")

但没有任何效果...

【问题讨论】:

    标签: r function evaluation


    【解决方案1】:

    使用deparse()substitute() 将符号转换为字符串:

    dataframe_test <- function(df1, df2) {
    
      varnames <- names(df1)[names(df1) %in% names(df2)]
      out <- data.frame(
        df1 = sapply(df1[,varnames], class),
        df2 = sapply(df2[,varnames], class)
      ) 
      out$Test <- ifelse(out$df1 == out$df2, " - ", "FLAG")
      names(out) <- c(deparse(substitute(df1)), deparse(substitute(df2)), "Test")
    
      return(out)
    
    }
    
    iris2 <- iris
    
    dataframe_test(iris, iris2)
    #>                 iris   iris2 Test
    #> Sepal.Length numeric numeric   - 
    #> Sepal.Width  numeric numeric   - 
    #> Petal.Length numeric numeric   - 
    #> Petal.Width  numeric numeric   - 
    #> Species       factor  factor   -
    

    reprex package (v0.3.0) 于 2020 年 4 月 22 日创建

    【讨论】:

      【解决方案2】:

      我们可以使用deparsesubstitute 来获取数据框名称并在ifelse 中按位置引用列名称。

      dataframe_test <- function(df1, df2) {
      
         data1 <- deparse(substitute(df1))
         data2 <- deparse(substitute(df2))
         varnames <- names(df1)[names(df1) %in% names(df2)]
         out <- setNames(data.frame(sapply(df1[,varnames], class),
                      sapply(df2[,varnames], class)), c(data1, data2))
         out$Test <- ifelse(out[[1]] == out[[2]], " - ", "FLAG")
         return(out)
      }
      
      dataframe_test(iris, iris2)
      
      #                iris   iris2 Test
      #Sepal.Length numeric numeric   - 
      #Sepal.Width  numeric numeric   - 
      #Petal.Length numeric numeric   - 
      #Petal.Width  numeric numeric   - 
      #Species       factor  factor   -
      

      【讨论】: