R语言:按列值导出多数据框列表至Excel的报错解决
按公司拆分多数据表并导出Excel(兼容缺失数据场景)
场景与问题
现有三个DataFrame(DF、DF2、DF3),需要按Company列的值导出独立Excel文件:每个文件对应一家公司,包含该公司在SpreadsheetA、SpreadsheetB、SpreadsheetC三个源表中的数据。但部分公司未在所有源表中出现,原代码因数据结构不匹配报错,需实现缺失数据的源表不生成对应工作表的效果。
示例数据
DF <- data.frame(Company=c('Alpha', 'Alpha', 'Alpha', 'Beta', 'Beta', 'Gamma', 'Epsilon'), Location=c('NY', 'NY', 'CHI', 'LA', 'CHI','LA', 'LA' ), ID=c('1234', '1234', '1234', '5678', '5678', '2468', '2468'), Charge=c(25,25,51, 60,60, 15, 15)) DF2 <- data.frame(Company=c('Alpha', 'Alpha', 'Beta', 'Beta', 'Delta', 'Delta', 'Delta'), Location=c('NY', 'NY', 'CHI', 'LA', 'CHI','LA', 'LA' ), ID=c('1234', '1234', '1234', '5678', '4567', '4567', '4567'), Charge=c(25,25,51, 60,60, 15, 15)) DF3 <- data.frame(Company=c('Alpha', 'Alpha', 'Beta', 'Delta', 'Delta','Delta','Delta'), Location=c('NY', 'NY', 'CHI', 'LA', 'CHI','LA', 'LA' ), ID=c('1234', '1234', '1234', '5678', '4567', '6789', '6789'), Charge=c(25,25,51, 60,60, 15, 15))
原错误代码
list( DF, DF2, DF3 ) %>% purrr::set_names(paste("SpreadsheetA"), paste("SpreadsheetB"), paste("SpreadsheetC"), paste("SpreadsheetD")) %>% purrr::map(~ split(.x, .x$Company)) %>% purrr::transpose() %>% purrr::iwalk(~writexl::write_xlsx(.x, file.path(path, paste0("results_", .y, ".xlsx"))))
报错原因:
transpose()要求每个拆分后的列表结构完全一致,但部分公司仅在部分表中存在,导致结构不匹配。
解决方案
核心思路:先收集所有唯一公司名,对每个公司单独遍历源表,仅保留该公司有数据的表,再导出Excel(无数据的表自动跳过,不生成工作表)。
修改后代码
library(purrr) library(writexl) # 1. 定义数据表列表并命名(修正原代码多余的SpreadsheetD) df_list <- list( SpreadsheetA = DF, SpreadsheetB = DF2, SpreadsheetC = DF3 ) # 2. 获取所有数据表中出现的唯一Company值 all_companies <- df_list %>% map(pull, Company) %>% unlist() %>% unique() # 3. 遍历每个公司,筛选数据并导出 walk(all_companies, function(company) { # 对每个源表,筛选当前公司的数据,仅保留有数据的表 company_data <- df_list %>% map(~ filter(.x, Company == company)) %>% keep(~ nrow(.x) > 0) # 导出Excel文件,无数据的表不会生成工作表 if(length(company_data) > 0) { write_xlsx( company_data, path = file.path(getwd(), paste0("results_", company, ".xlsx")) ) } })
代码说明
df_list:直接给三个数据表命名为对应的源表名称,简化原代码中冗余的set_names写法。all_companies:收集所有出现过的公司名,确保不会遗漏任何公司。map(...) %>% keep(...):对每个源表筛选当前公司的数据,用keep过滤掉空表(无数据的表)。- 导出逻辑:仅当存在有效数据时才生成文件,避免空文件产生。
内容的提问来源于stack exchange,提问作者CuRious Coder
相关产品推荐
相关产品推荐

