R для объединения всех листов из всех файлов Excel

Я пытаюсь объединить данные со всех листов во всех файлах Excel в папке. Все листы и все файлы имеют одинаковые заголовки и одинаковые наборы данных. Я думал, что приведенный ниже код будет читать все листы, но, похоже, он читает ТОЛЬКО первый лист в каждом файле.

# This needs several other packages
# install.packages("XLConnect")
require(XLConnect)

setwd("C:/Users/Excel/Desktop/Coding/R Programming/Excel/Excel_Files/")

fpattern <- "File.*.xls*?"  # pattern for filenames
output.file <- "Test.xls"
lfiles <- list.files(pattern = fpattern)

# Read data from all sheets
lfiles %>% 
  excel_sheets() %>% 
  set_names() %>% 
  map(read_excel, lfiles = lfiles)

person ASH    schedule 14.07.2018    source источник
comment
Где именно проблема? Там много кода после того, где, как вы говорите, проблема. Если в этом нет необходимости, сделайте пример как можно более минимальным.   -  person Aaron left Stack Overflow    schedule 14.07.2018
comment
Что ж, думаю, я осветил проблему, верно. По крайней мере, насколько я понимаю. Думаю, вот оно: lfiles% ›% excel_sheets ()%›% set_names ()% ›% map (read_excel, lfiles = lfiles) Кажется, что он извлекает данные из первого листа в книге, но не из всех листов в книге .   -  person ASH    schedule 14.07.2018
comment
В отличие от других сайтов QA, здесь, на SO, вопросы можно редактировать; отредактируйте свой вопрос, чтобы отразить, в чем проблема (и удалить ненужный код).   -  person Aaron left Stack Overflow    schedule 15.07.2018
comment
Я просто попытался упростить свой вопрос.   -  person ASH    schedule 18.07.2018
comment
Намного лучше, спасибо. Еще одно предложение: пакет readxl - это новейший и лучший способ чтения файлов Excel; если вы можете переключиться на это, у вас больше шансов получить помощь.   -  person Aaron left Stack Overflow    schedule 18.07.2018


Ответы (2)


Это пример с использованием только базовых функций R и XLConnect:

library(XLConnect)

testDir <- "Excel_Files"

re_file <- ".+\\.xls.?"
testFiles <- list.files(testDir, re_file, full.names = TRUE)

# This function rbinds in a single dataframe
# the content of multiple sheets in the same workbook
# (assuming that all the sheets have the same column types)
rbindAllSheets <- function(file) {
  wb <- loadWorkbook(file)
  sheets <- getSheets(wb)
  do.call(rbind,
          lapply(sheets, function(sheet) {
            readWorksheet(wb, sheet)
          })
  )
}

# Getting a single dataframe for all the Excel files
result <- do.call(rbind, lapply(testFiles, rbindAllSheets))
person Nicola Lambiase    schedule 21.07.2018

Я думаю, что следующее делает то, что вы ищете. В этом примере не каждый файл имеет одинаковые листы или столбцы; 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
person sbha    schedule 18.07.2018
comment
Привет. Это выглядит довольно близко, но что-то в моей настройке должно отличаться от вашей. Я получаю такой результат: df # Tibble: 0 x 2 # ... с двумя переменными: file_name ‹chr›, sheet_name ‹chr› Для чего это? re_file ‹- ^ test [0-9] \\. xlsx Кроме того, для чего это нужно? .id = 'имя_листа' - person ASH; 18.07.2018
comment
re_file - это шаблон регулярного выражения, который list.files() использует для получения имен файлов xlsx в каталоге. В этом примере он соответствует любому файлу, который соответствует формату именования 'test [single digit] .xlsx', но похоже, что вы могли бы сделать только re_pattern = 'File.*\\.xlsx'. .id = 'sheet_name' просто добавляет имя листа в виде столбца. Вы можете заменить 'sheet_name' на то, что вы хотите, чтобы столбец был. Это необязательный аргумент. - person sbha; 18.07.2018
comment
Я продолжаю получать такой результат: # Тиббл: 0 x 0 Я думаю, он не обнаруживает ни одного из файлов. Раньше я получал первый лист каждого файла, но теперь я вообще ничего не получаю. Фу. - person ASH; 18.07.2018
comment
Возможно, проблема в том, что регулярное выражение соответствует форматам имен файлов. При вызове только list.files(dir_path, re_file) перечисляются ожидаемые файлы? - person sbha; 18.07.2018
comment
И если вызов list.files() работает, как ожидалось, попробуйте функцию read_sheets() с единственным именем файла: read_sheets('~/sample/path/', 'sample_file_name.xlsx') и посмотрите, работает ли это так, как ожидалось. - person sbha; 18.07.2018
comment
Отсюда я нашел другое решение, которое сработало для меня: stackoverflow.com/questions/51200887/ Я думаю, ваше решение выглядит нормально, но какая-то мелочь должен быть выключен, и это мешает мне получать данные из этих файлов Excel. Спасибо хоть. Я отметил ваш ответ как полезный. Опять же, я думаю, что проблема в стороне. - person ASH; 18.07.2018