Как перейти от веселья к списку в dplyr, когда используется имя столбца? - PullRequest
5 голосов
/ 03 ноября 2019

Я пытаюсь переключить свой код с funs () (package dplyr ) на list () , особенно в mutate_if () function.

К сожалению, у меня есть один фрагмент кода, который использует имя столбца в качестве входного параметра. Но при использовании функции 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 голосов
/ 03 ноября 2019

Не должно быть . внутри list() функций:

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

  A     B    
  <chr> <chr>
1 A     B    
2 A     B  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...