R read_xlsx函数导入带过滤器的excel文件

bkhjykvo  于 2023-07-31  发布在  其他
关注(0)|答案(2)|浏览(81)

我有几十个excel文件,我想导入到R进行进一步的处理和分析。这些是每个月的文件。源文件带有过滤器,其中包括不需要的数据。我想使用readxl包中的read_xlsx函数。然而,所有行都被导入到R中,包括不需要的行。我知道我可以导入所有文件,然后做过滤的事情或只是复制粘贴原始excel文件。我想知道的是,在read_xlsx步骤中是否可以将过滤器保留在文件中,这是目前对我来说最好的选择。
先谢谢你,
菲利克斯

igetnqfo

igetnqfo1#

除了@stefan的答案之外,还可以使用下面的openxlsx2找到一个。基本上,被筛选的行在工作表中是隐藏的。此信息存储在行中,通过openxlsx2导入,因此可用于跳过此类行。

library(openxlsx2)

tmp <- temp_xlsx()

# create a file
wb <- wb_workbook()$
  add_worksheet()$add_data(x = mtcars, withFilter = TRUE)$
  add_worksheet()$add_data_table(x = mtcars)$
  save(tmp)

# apply filter and save it (I choose mpg < 20 in `Sheet 1` and mpg > 20 in `Sheet 2`)
xl_open(tmp)

字符串
现在来回答这个问题:

# first sheet:  mpg < 20
sheet1 <- wb_to_df(tmp, sheet = 1, skipHiddenRows = TRUE)
head(sheet1)
#>     mpg cyl  disp  hp drat   wt  qsec vs am gear carb
#> 6  18.7   8 360.0 175 3.15 3.44 17.02  0  0    3    2
#> 7  18.1   6 225.0 105 2.76 3.46 20.22  1  0    3    1
#> 8  14.3   8 360.0 245 3.21 3.57 15.84  0  0    3    4
#> 11 19.2   6 167.6 123 3.92 3.44 18.30  1  0    4    4
#> 12 17.8   6 167.6 123 3.92 3.44 18.90  1  0    4    4
#> 13 16.4   8 275.8 180 3.07 4.07 17.40  0  0    3    3

# second sheet: mpg > 20
sheet2 <- wb_to_df(tmp, sheet = 2, skipHiddenRows = TRUE)
head(sheet2)
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 2  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 3  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 4  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 5  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 9  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 10 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2


PS:我们目前正在精简我们的API,并将支持snake case参数(尽管上面的代码仍然会运行)。

ne5o7dgx

ne5o7dgx2#

不久前,我也在为同样的问题而挣扎。经过一些研究和AFAIK的简短回答是(仍然),这不能通过readxl实现。此外,AFAIK在openxlsx或...等软件包中也(仍然)没有开箱即用的选项。
但是,由于openxlsx可以读取excel工作簿对象,因此它允许检索有关设置过滤器的信息,然后可以使用这些信息将过滤器应用于导入的数据集。
下面的代码是如何实现这一点的一个示例。
注意:代码在我的用例中工作得很好,但它并不意味着是一个通用的开箱即用的解决方案,因此您可能必须调整代码以满足您的需求。
首先,让我们创建一个示例excel文件,我使用mtcars数据集:

library(openxlsx)

wb <- createWorkbook()
addWorksheet(wb, "filter")
writeDataTable(wb, "filter", mtcars)
saveWorkbook(wb, "test-filter.xlsx")

字符串
其次,在MS Excel中,我在表格上设置了两个过滤器,即我在cyl列上设置了一个过滤器,在carb列上设置了第二个过滤器:


的数据
下面的代码使用了一个自定义函数。

scrape_filter <- function(table) {
  x <- xml2::read_xml(table)|>
    xml2::xml_child(1)|>
    xml2::xml_children()

  col_id <- x|>
    xml2::xml_attrs()|>
    purrr::map_chr(1)

  vals <- purrr::map_chr(x, function(x) {
    xml2::xml_child(x, 1)|>
      xml2::xml_children()|>
      xml2::xml_attrs()|>
      purrr::map_chr(1)|>
      paste(collapse = "; ")
  })

  data.frame(col_id, vals) |> 
    select(col_id, vals) |>
    mutate(col_id = names(dat)[as.integer(.data$col_id) + 1]) |>
    mutate(filter_cond = if_else(
      .data$vals %in% "notEqual", glue::glue("!is.na({col_id})"),
      glue::glue('{col_id} %in% str_split("{vals}", "; ")[[1]]')
    ))
}


在加载数据和工作簿后,可以用它来提取设置过滤器的信息并解析它们...

library(tidyverse)
library(xml2)
library(readxl)
library(openxlsx)
library(glue)

fn <- "test-filter.xlsx"

dat <- readxl::read_xlsx(path = fn)

wb <- loadWorkbook(fn)

filters <- scrape_filter(wb$tables)

R> filters
  col_id vals                           filter_cond
1    cyl 4; 8 cyl %in% str_split("4; 8", "; ")[[1]]
2   carb    2   carb %in% str_split("2", "; ")[[1]]


...最后,在使用rlang::parse_exprs的导入数据集上应用过滤器

filter(dat, !!!rlang::parse_exprs(filters$filter_cond))

# A tibble: 10 × 11
     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  18.7     8 360     175  3.15  3.44  17.0     0     0     3     2
 2  24.4     4 147.     62  3.69  3.19  20       1     0     4     2
 3  22.8     4 141.     95  3.92  3.15  22.9     1     0     4     2
 4  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
 5  15.5     8 318     150  2.76  3.52  16.9     0     0     3     2
 6  15.2     8 304     150  3.15  3.44  17.3     0     0     3     2
 7  19.2     8 400     175  3.08  3.84  17.0     0     0     3     2
 8  26       4 120.     91  4.43  2.14  16.7     0     1     5     2
 9  30.4     4  95.1   113  3.77  1.51  16.9     1     1     5     2
10  21.4     4 121     109  4.11  2.78  18.6     1     1     4     2


还有两个注意事项:

  • 在我的例子中,数据存储在表中,自定义函数只对表起作用。
  • 在这个例子中,我只有一个工作表和一个表格。在我的用例中,excel文件包含多个工作表,每个工作表一个表。在这种情况下,您可以或必须使用lapplypurrr::map来迭代表和工作表。

相关问题