Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
422 views
in Technique[技术] by (71.8m points)

r - How to change the now deprecated dplyr::funs() which includes an ifelse argument?

Pretty basic but I don't think I really understand the change:

library(dplyr)
library(lubridate)

Lab_import_sql <- Lab_import %>%
    select_if(~sum(!is.na(.)) > 0) %>%
    mutate_if(is.factor, as.character) %>%
    mutate_if(is.character, funs(ifelse(is.character(.), trimws(.),.))) %>%
    mutate_at(.vars = Lab_import %>% select_if(grepl("'",.)) %>% colnames(),
                 .funs = gsub,
                 pattern = "'",
                 replacement = "''") %>%
    mutate_if(is.character, funs(ifelse(is.character(.), paste0("'", ., "'"),.))) %>%
    mutate_if(is.Date, funs(ifelse(is.Date(.), paste0("'", ., "'"),.)))

Edit:

Thanks everyone for the input, here's reproducible code and my solution:

library(dplyr)
library(lubridate)

import <- data.frame(Test_Name = "Fir'st Last", 
                     Test_Date = "2019-01-01", 
                     Test_Number = 10)

import_sql <-import %>%
  select_if(~!all(is.na(.))) %>%
  mutate_if(is.factor, as.character) %>%
  mutate_if(is.character, trimws) %>%
  mutate_if(is.character, list(~gsub("'", "''",.))) %>% 
  mutate_if(is.character, list(~paste0("'", ., "'"))) %>%
  mutate_if(is.Date, list(~paste0("'", ., "'")))
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As of dplyr 0.8.0, the documentation states that we should use list instead of funs, giving the example:

Before:

funs(name = f(.))

After:

list(name = ~f(.))

So here, the call funs(ifelse(is.character(.), trimws(.),.)) can become instead list(~ifelse(is.character(.), trimws(.),.)). This is using the formula notation for anonymous functions in the tidyverse, where a one-sided formula (expression beginning with ~) is interpreted as function(x), and wherever x would go in the function is represented by .. You can still use full functions inside list.

Note the difference between the .funs argument of mutate_if and the funs() function which wrapped other functions to pass to .funs; i.e. .funs = gsub still works. You only needed funs() if you needed to apply multiple functions to selected columns or to name them something by passing them as named arguments. You can do all the same things with list().

You also are duplicating work by adding ifelse inside mutate_if; that line could be simplified to mutate_if(is.character, trimws) since if the column is character already you don't need to check it again with ifelse. Since you apply only one function, no need for funs or list at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...