如何解决map()传变量列表给自定义函数时的长度不匹配报错
问题解决:向自定义函数传递字符串向量批量处理数据框列表
自定义函数需求
- 接收数据框列表(data frame list)和字符串参数
- 执行数据过滤与转换操作
- 返回转换后的data frame
可复现代码
# 生成4个包含重复观测的数据框 df_1 <- data.frame(col1 = c(1, 2, 3, 4), col2 = c('apple', 'pineapple', 'orange', 'grape')) df_2 <- data.frame(col1 = c(2, 3, 4, 5, 6, 7), col2 = c('watermelon', 'orange', 'halibut', 'apple', 'iron', 'grape')) df_3 <- data.frame(col1 = c(2, 3, 4, 5, 6, 7, 9, 0), col2 = c('rock', 'pineapple', 'apple', 'tire', 'bomb', 'star', 'coconut', 'grape')) df_4 <- data.frame(col1 = c(1, 4, 9), col2 = c('grape', 'apple', 'rock')) # 将数据框存入列表 df_list <- list(df_1, df_2, df_3, df_4) # 定义自定义函数 toy_function <- function(df_list, var1) { map(df_list, ~.x %>% filter(col2 == var1) %>% mutate(result = col1 * 2)) %>% bind_rows() %>% select(result) } # 单个参数调用正常运行 toy_function(df_list = df_list, var1 = 'apple')
问题:传递字符串向量时报错
尝试传递字符串向量批量处理时,出现长度不匹配的错误:
# 待处理的字符串向量 list_of_fruits <- c('apple', 'grape') # 错误调用方式 map2(.x = df_list, .y = list_of_fruits, .f = toy_function) # 错误信息 Error in `map2()`: ! Can't recycle `.x` (size 4) to match `.y` (size 2). Run `rlang::last_trace()` to see where the error occurred.
期望结果
希望得到每个字符串对应的处理结果列表:
# 期望输出 [[1]] result 1 2 2 10 3 8 4 8 [[2]] result 1 8 2 14 3 0 4 2
修改函数后仍报错
尝试将==改为%in%以支持向量匹配,但调用方式错误导致问题依旧:
toy_function <- function(df_list, var1) { map(df_list, ~ { filtered_df <- .x %>% filter(col2 %in% var1) filtered_df %>% mutate(result = col1 * 2) %>% select(result) }) %>% bind_rows() }
解决方案
错误原因
map2的作用是将.x和.y的对应位置元素配对传入函数,但这里需要的是对list_of_fruits中的每个元素,都用完整的df_list来处理,而非将df_list的元素与fruits元素一一配对。
正确实现
方法1:使用map遍历字符串向量
直接用map遍历list_of_fruits,每个元素作为var1传入函数,固定传入df_list:
library(purrr) library(dplyr) # 保持原函数(或使用%in%版本均可) toy_function <- function(df_list, var1) { map(df_list, ~.x %>% filter(col2 == var1) %>% mutate(result = col1 * 2)) %>% bind_rows() %>% select(result) } # 正确调用方式 map(list_of_fruits, ~toy_function(df_list, .x))
方法2:修改函数支持批量处理并返回列表(可选)
如果希望函数直接接收字符串向量并返回结果列表,可修改函数内部逻辑:
toy_function_batch <- function(df_list, var_vec) { map(var_vec, function(var) { map(df_list, ~.x %>% filter(col2 == var) %>% mutate(result = col1 * 2)) %>% bind_rows() %>% select(result) }) } # 调用 toy_function_batch(df_list, list_of_fruits)
两种方法均能得到预期的结果列表。
内容的提问来源于stack exchange,提问作者toku_mo
相关产品推荐
相关产品推荐

