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

时间:2019-11-03 11:23:33

标签: 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 .     .    

结果不太一样。 :-(

我尝试了很多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

1 个答案:

答案 0 :(得分:0)

函数.中不应有list()

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

  A     B    
  <chr> <chr>
1 A     B    
2 A     B