如何在R中将Excel工作表名称作为ID列添加到最终dataframe中
问题
我用以下代码从单个Excel文件导入多个工作表,生成的dataframe名称和工作表名称一致(比如工作表名为"a",R里就生成同名dataframe"a"):
sheetnames <- readxl::excel_sheets(raw.data.dir) mylist <- lapply(readxl::excel_sheets(raw.data.dir), readxl::read_excel, path = raw.data.dir) # 命名数据框 names(mylist) <- sheetnames # 将数据框导入全局环境 list2env(mylist ,.GlobalEnv)
现在想给每个生成的dataframe自动添加一列,填充对应的工作表名称,不用手动操作。
可复现示例:
a = data.frame( y1 = c(1, 2, 3), y2 = c(4, 5, 6) ) b = data.frame( y1 = c(7, 8, 9), y2 = c(1, 4, 6) ) sheetnames <- c("a","b") mylist = list(a, b) names(mylist) <- sheetnames list2env(mylist ,.GlobalEnv)
运行后得到的dataframe a是:
y1 y2 1 1 4 2 2 5 3 3 6
希望自动处理后得到:
y1 y2 id 1 1 4 a 2 2 5 a 3 3 6 a
解决方法
方法一:用Map配对工作表名与数据框
核心思路是在读取数据(或处理已有列表)时,将工作表名和对应的数据框配对,给每个数据框添加对应名称的列,再导入全局环境。
针对Excel读取场景的完整代码:
sheetnames <- readxl::excel_sheets(raw.data.dir) # 使用Map同时处理工作表名和读取操作,添加id列 mylist <- Map(function(sheet, path) { df <- readxl::read_excel(path, sheet = sheet) df$id <- sheet # 新增列填充对应工作表名称 df }, sheetnames, MoreArgs = list(path = raw.data.dir)) names(mylist) <- sheetnames list2env(mylist, .GlobalEnv)
针对你提供的可复现示例,修改后的代码:
a = data.frame( y1 = c(1, 2, 3), y2 = c(4, 5, 6) ) b = data.frame( y1 = c(7, 8, 9), y2 = c(1, 4, 6) ) sheetnames <- c("a","b") mylist = list(a, b) # 给列表中每个数据框添加对应名称的id列 mylist <- Map(function(df, name) { df$id <- name df }, mylist, sheetnames) names(mylist) <- sheetnames list2env(mylist, .GlobalEnv)
方法二:用purrr::imap简化操作
如果你习惯使用tidyverse工具链,purrr包的imap函数可以更简洁地实现,它会同时遍历列表的元素和元素名称:
library(purrr) library(dplyr) sheetnames <- readxl::excel_sheets(raw.data.dir) mylist <- lapply(sheetnames, readxl::read_excel, path = raw.data.dir) |> set_names(sheetnames) |> imap(\(df, name) mutate(df, id = name)) # 新增id列,值为对应工作表名 list2env(mylist, .GlobalEnv)
运行任意一种方法后,每个导入的dataframe都会自动新增一列(示例中为id),填充对应的工作表名称。
内容的提问来源于stack exchange,提问作者myfatson
相关产品推荐
相关产品推荐

