【问题标题】:How to import multiple sheets from multiple excel files into one list- readxl R如何将多个excel文件中的多张工作表导入一个列表-readxl R
【发布时间】:2018-07-05 22:52:10
【问题描述】:

我看过其他帖子,详细介绍了如何将单个 excel 文件中的多个工作表导入 R,以及如何导入一系列每个都有一个工作表但不能同时包含两个工作表的 excel 文件。

我能够使以下代码在单个文件级别分段工作,但我认为我可能以某种简单的方式搞砸了循环。

当我执行循环时,我只从列表的第一个成员 (files[1]) 中获取输出,而不是从附加在 all_data 列表对象中的循环的所有迭代中获取输出。

这是我的代码:

# name filepath of excel files to import
file_path ="..."

# load names of excel files 
files = list.files(path = file_path, pattern = ".xlsx", )

# create list to store data
all_data = list()

# create function to read multiple sheets per excel file
read_excel_allsheets <- function(filename, tibble = FALSE) {
  sheets <- readxl::excel_sheets(filename)
  x <- lapply(sheets, function(X) readxl::read_excel(filename, sheet = X))
  x <- lapply(x, as.data.frame)
  names(x) <- sheets
  }

# execute function for all excel files in "files"
for (i in length(files)){
  filename = paste0(file_path,"/", files[i])
  read_excel_allsheets(filename)
  all_data = c(all_data, x)
  }

我怀疑我只是犯了一个基本的循环错误,但我四处搜索却找不到解决方法。非常感谢任何帮助!

【问题讨论】:

  • 几个 cmets:list.files 有 full.names 参数,所以你不必预先添加路径。 read_excel 返回 tibbles,所以你不需要强制它到 data.frame。在循环内部,您没有将 real_excel_allsheets() 函数的结果分配给变量(我猜它应该是 x)。您创建了一个空列表并在循环内增长它。将其预分配给length(files) 并由元素i 分配
  • 所有文件/选项卡中的数据结构相同吗?

标签: r excel function loops import


【解决方案1】:

看看这样的东西是否适合你:

library(readxl)
library(fs)
library(purrr)

file_names <- dir_ls("folder_name",
                     glob = "*.xlsx", ignore.case = TRUE)

x <- map_df(file_names, function(x){  
                 sheet_names <- excel_sheets(x)
                 raw_data <- map_df(sheet_names, ~read_excel(x, sheet = .x)) 
                 return(raw_data)})

【讨论】:

    【解决方案2】:

    对于多个 Excel 文件中的多个工作表,您需要嵌套循环。考虑嵌套的lapply 调用。具体来说,返回适当的对象,因为它现在为每个函数调用返回 sheets。然后,将for 转换为lapply 以获得对象列表:

    # load names of excel files 
    files = list.files(path = "...", full.names = TRUE, pattern = ".xlsx")
    
    # create function to read multiple sheets per excel file
    read_excel_allsheets <- function(filename, tibble = FALSE) {
      sheets <- readxl::excel_sheets(filename)
      tibble_list <- lapply(sheets, function(sh) readxl::read_excel(filename, sheet = sh)
      df_list <- lapply(x, as.data.frame)
      names(df_list) <- sheets                 
    
      return(df_list)
    }
    
    # execute function for all excel files in "files"
    all_data <- lapply(files, read_excel_allsheets)
    

    甚至按每个文件的基本名称列出all_data

    # name outer list
    xl_base_names <- lapply(files, basename)
    all_data <- setNames(all_data, xl_base_names)
    

    或者,缩短您的函数并使用sapply(..., ..., simplify = FALSE),默认情况下,名称按提供的字符向量列出:

    read_excel_allsheets <- function(filename, tibble = FALSE) {
      sheets <- readxl::excel_sheets(filename)
      sapply(sheets, function(f) as.data.frame(readxl::read_excel(filename, sheet = f)), 
             simplify = FALSE)
    }
    

    【讨论】:

    • 这真的很有帮助-感谢您抽出时间来解释!
    【解决方案3】:

    这是一个选项,它返回一个数据框,其中包含文件列和每个文件的工作表名称。在此示例中,并非每个文件都具有相同的工作表或列; test2.xlsx 只有一张,test3.xlsx sheet1 没有 col3。

    library(tidyverse)
    library(readxl)
    
    dir_path <- "~/test_dir/"         # target directory where the xlsx files are located. 
    re_file <- "^test[0-9]\\.xlsx"    # regex pattern to match the file name format, in this case 'test1.xlsx', 'test2.xlsx' etc.
    
    read_sheets <- function(dir_path, file){
      xlsx_file <- paste0(dir_path, file)
      xlsx_file %>%
        excel_sheets() %>%
        set_names() %>%
        map_df(read_excel, path = xlsx_file, .id = 'sheet_name') %>% 
        mutate(file_name = file) %>% 
        select(file_name, sheet_name, everything())
    }
    
    df <- list.files(dir_path, re_file) %>% 
      map_df(~ read_sheets(dir_path, .))
    
    # A tibble: 15 x 5
       file_name  sheet_name  col1  col2  col3
       <chr>      <chr>      <dbl> <dbl> <dbl>
     1 test1.xlsx Sheet1         1     2     4
     2 test1.xlsx Sheet1         3     2     3
     3 test1.xlsx Sheet1         2     4     4
     4 test1.xlsx Sheet2         3     3     1
     5 test1.xlsx Sheet2         2     2     2
     6 test1.xlsx Sheet2         4     3     4
     7 test2.xlsx Sheet1         1     3     5
     8 test2.xlsx Sheet1         4     4     3
     9 test2.xlsx Sheet1         1     2     2
    10 test3.xlsx Sheet1         3     9    NA
    11 test3.xlsx Sheet1         4     7    NA
    12 test3.xlsx Sheet1         5     3    NA
    13 test3.xlsx Sheet2         1     3     4
    14 test3.xlsx Sheet2         2     5     9
    15 test3.xlsx Sheet2         4     3     1
    

    【讨论】:

      猜你喜欢
      • 2020-07-30
      • 2018-07-09
      • 1970-01-01
      • 2020-02-03
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 2021-01-27
      • 2018-09-30
      相关资源
      最近更新 更多