既然你提到了
purrr
包,其他一些tidyverse包值得考虑。
-
dplyr
对于
mutate()
purrr::map()
并将结果存储为列表列。
-
tidyr
对于
unnest()
,它扩展列表列,使列表列中的每一行成为整个数据帧中的一行。
-
tibble
用于打印精美的嵌套数据帧
需要示例文件进行演示。此代码使用
openxlsx
包创建一个包含两张图纸的文件(内置
iris
mtcars
数据集)和另一个包含三张图纸的文件(添加内置
attitude
数据集)。
library(openxlsx)
# Create two spreadsheet files, with different numbers of worksheets
write.xlsx(list(iris, mtcars, attitude), "three_sheets.xlsx")
write.xlsx(list(iris, mtcars), "two_sheets.xlsx")
现在是一个解决方案。
首先,列出文件名,该文件名将传递给
readxl::excel_sheets()
每个文件中图纸的名称,以及
readxl::read_excel()
导入数据本身。
(paths <- list.files(pattern = "*.xlsx"))
#> [1] "three_sheets.xlsx" "two_sheets.xlsx"
(x <- tibble::data_frame(path = paths))
#> # A tibble: 2 x 1
#> path
#> <chr>
#> 1 three_sheets.xlsx
#> 2 two_sheets.xlsx
“映射”
readxl::excel_sheets()
在每个文件路径上运行,并将结果存储在新的列表列中。每行
sheet_name
列是图纸名称的向量。正如所料,第一个有三个图纸名称,而第二个有两个。
(x <- dplyr::mutate(x, sheet_name = purrr::map(path, readxl::excel_sheets)))
#> # A tibble: 2 x 2
#> path sheet_name
#> <chr> <list>
#> 1 three_sheets.xlsx <chr [3]>
#> 2 two_sheets.xlsx <chr [2]>
我们需要将每个文件名和每个工作表名传递到
readxl::read_excel(path=, sheet=)
,因此下一步是创建一个数据框,其中每行提供一个路径和一个图纸名称。这是通过使用
tidyr::unnest()
.
(x <- tidyr::unnest(x))
#> # A tibble: 5 x 2
#> path sheet_name
#> <chr> <chr>
#> 1 three_sheets.xlsx Sheet 1
#> 2 three_sheets.xlsx Sheet 2
#> 3 three_sheets.xlsx Sheet 3
#> 4 two_sheets.xlsx Sheet 1
#> 5 two_sheets.xlsx Sheet 2
现在可以将每个路径和图纸名称传递到
readxl::read\u excel()
,使用
purrr::map2()
而不是
purrr::map()
因为我们传递了两个参数,而不是一个。
(x <- dplyr::mutate(x, data = purrr::map2(path, sheet_name,
~ readxl::read_excel(.x, .y))))
#> # A tibble: 5 x 3
#> path sheet_name data
#> <chr> <chr> <list>
#> 1 three_sheets.xlsx Sheet 1 <tibble [150 Ã 5]>
#> 2 three_sheets.xlsx Sheet 2 <tibble [32 Ã 11]>
#> 3 three_sheets.xlsx Sheet 3 <tibble [30 Ã 7]>
#> 4 two_sheets.xlsx Sheet 1 <tibble [150 Ã 5]>
#> 5 two_sheets.xlsx Sheet 2 <tibble [32 Ã 11]>
现在,每个数据集位于
data
柱通过对该列进行子集划分,我们可以只查看其中一个数据集。
x$data[3]
#> [[1]]
#> # A tibble: 30 x 7
#> rating complaints privileges learning raises critical advance
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 43.0 51.0 30.0 39.0 61.0 92.0 45.0
#> 2 63.0 64.0 51.0 54.0 63.0 73.0 47.0
#> 3 71.0 70.0 68.0 69.0 76.0 86.0 48.0
#> 4 61.0 63.0 45.0 47.0 54.0 84.0 35.0
#> 5 81.0 78.0 56.0 66.0 71.0 83.0 47.0
#> 6 43.0 55.0 49.0 44.0 54.0 49.0 34.0
#> 7 58.0 67.0 42.0 56.0 66.0 68.0 35.0
#> 8 71.0 75.0 50.0 55.0 70.0 66.0 41.0
#> 9 72.0 82.0 72.0 67.0 71.0 83.0 31.0
#> 10 67.0 61.0 45.0 47.0 62.0 80.0 41.0
#> # ... with 20 more rows