使用列名称时,如何从Funs切换到dplyr中的列表?

Han*_* H. 5 r dplyr

我尝试将代码从funs ()(软件包dplyr)切换到list(),尤其是在mutate_if()函数中。

不幸的是,我有一段使用列名作为输入参数的代码。但是,当使用list()函数时,代码会中断!

此示例代码仅将列的内容替换为列名:

library(tibble)
library(dplyr)

atibble=tribble(~A, ~B,
                "A1", "B1",
                "A2", "B2")

print(atibble)

## A tibble: 2 x 2
#  A     B    
#  <chr> <chr>
#1 A1    B1   
#2 A2    B2   

atibble %>% 
  mutate_if(is.character, funs(quo_name(quo(.))))

## A tibble: 2 x 2
#  A     B    
#  <chr> <chr>
#1 A     B    
#2 A     B 

atibble %>% 
  mutate_if(is.character, list(~quo_name(quo(.))))

## A tibble: 2 x 2
#  A     B    
#  <chr> <chr>
#1 .     .    
#2 .     .    
Run Code Online (Sandbox Code Playgroud)

结果不太一样。:-(

我尝试了很多quo,enquo,rlang :: as_name,..的组合,但是没有任何帮助。

如何修复list()语句,使代码显示与funs()相同的结果?

我的环境:

  • Windows 10
  • R版本3.6.1
  • dplyr版本0.8.3

谢谢

编辑:tmfmnk的解决方案。我只想在这里显示整个问题。如果有人找到没有助手功能的解决方案,我将很高兴看到它。:-)

library(tibble)
library(dplyr)
library(lubridate)

# my original problem involves dates.
btibble=tribble(~A, ~B,
                ymd("2019-11-04"), ymd("2019-10-20"),
                ymd("2018-02-12"), ymd("2019-02-06"))

# # A tibble: 2 x 2
#   A          B         
#   <date>     <date>    
# 1 2019-11-04 2019-10-20
# 2 2018-02-12 2019-02-06

# And I have a small function that I use.
# It determines the granularity I want for the date column.
getDateUnit <- function(x) {
  if (x == 'A') {
    return ("month")
  }
  return("year")
}

# works fine with funs.
btibble %>%
  mutate_if(is.Date, funs(floor_date(., getDateUnit(quo_name(quo(.))))))

# Column A is on the first of the month, column B is on the first of the year.
# # A tibble: 2 x 2
#   A          B         
#   <date>     <date>    
# 1 2019-11-01 2019-01-01
# 2 2018-02-01 2019-01-01

# does not work with list because the function call is getDateUnit('.').
# every column will be set to first day of year now
btibble %>%
  mutate_if(is.Date, list(~floor_date(., getDateUnit(quo_name(quo(.))))))

# Column A is not formatted by month, but by year.
# # A tibble: 2 x 2
#   A          B         
#   <date>     <date>    
# 1 2019-01-01 2019-01-01
# 2 2018-01-01 2019-01-01

# Throws error
btibble %>%
  mutate_if(is.Date, list(function(x) floor_date(x, getDateUnit(quo_name(enquo(x))))))

# Error: `expr` must quote a symbol, scalar, or call
# Call `rlang::last_error()` to see a backtrace. 

# The workaround I found was using a helper function that 
# does the computing in two steps:
helper_function <- function(x) {
  unit = getDateUnit(quo_name(enquo(x)))
  return(floor_date(x, unit))
}

# with the helper function both snippets below work.
btibble %>%
  mutate_if(is.Date, helper_function)

btibble %>%
  mutate_if(is.Date, list(helper_function))

# # A tibble: 2 x 2
#   A          B         
#   <date>     <date>    
# 1 2019-11-01 2019-01-01
# 2 2018-02-01 2019-01-01

Run Code Online (Sandbox Code Playgroud)

tmf*_*mnk 0

.of 函数内部不应该有list()

atibble %>%
 mutate_if(is.character, list(function(x) quo_name(enquo(x))))

  A     B    
  <chr> <chr>
1 A     B    
2 A     B  
Run Code Online (Sandbox Code Playgroud)