简体   繁体   中英

My R function accepts individual column names but not lists of column names when passed through map()

After many months of using this forum, I finally have a question for the community that I can't seem to find sufficiently addressed elsewhere.

In R, I created a function that accepts individual column names but not lists of column names when passed through map(). The problem appears to be one of evaluation, so have tried quo() and enquo(), but since I don't properly understand how they work, I need some help.

I've tried iterating through different versions of the function (commenting out the offending lines as per error messages) but this only moves the problem around without solving it. Thanks in advance.

# Load:
library(tidyverse)

# Create df:
set.seed(12)
df <- tibble(col1 = sample(c("a", "b", "c"), 10, replace = TRUE),
             col2 = sample(1:4, 10, replace = TRUE),
             col3 = sample(1:4, 10, replace = TRUE))

# My function:
my_function <- function(col_name) {
  
  df <- df %>%
    filter({{ col_name }} != 1) %>%
    group_by(fct_relevel(factor(col1), "c", "b", "a")) %>%
    mutate(col4 = 5 - {{ col_name }}) %>%
    summarise("Score" = mean(col4)) %>%
    rename("Levels" =
             `fct_relevel(factor(col1), "c", "b", "a")`)
  
  return(df)
  
}

# List of col_names to pass to function:
col_list <- list(df$col2, df$col3)

# Attempt function in map() using list of col_names:
map(col_list, my_function)

# Gives error message:
# Error in `mutate()`:
# ! Problem while computing `col4 = 5 - c(1L, 2L, 1L, 2L,
#                                        4L, 2L, 2L, 3L, 4L, 1L)`.
# ✖ `col4` must be size 2 or 1, not 10.
# ℹ The error occurred in group 1: fct_relevel(factor(col1), "c",
#                                             "b", "a") = c.

One issue you're having is that col_list is not actually a list of column names, but rather the actual data from those columns.

I'm not totally sure what output you're hoping for, but I'm guessing it's the full_join of the result of my_function applied to each column. One way to do that is:

new_f <- function(...){
    df %>% 
        mutate(across(-col1, ~if_else(.x == 1L, NA, .x))) %>% 
        group_by("Levels" = fct_relevel(factor(col1), "c", "b", "a")) %>% 
        select(Levels, ...) %>% 
        summarize(across(everything(), ~ mean(5- .x, na.rm = TRUE)))
}

new_f(col2, col3)
new_f(col2)
new_f(col3)

Now, I realize that maybe I have missed your true intention. For example, maybe you're trying to understand how to use purrr::map . If so, please comment or update your question.

In any case, you should check out Programming with dplyr

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM