1.1 readxl

readxl 软件包使 R 获取 Excel 数据变得方便简洁。与现有的软件包(例如:xlsx)相比,readxl 没有外部依赖性,xlsx 等包依赖 java 环境。readxl 包容易在所有的操作系统安装使用。

readxl项目地址,本节大部分代码来源项目官网介绍,可自行查阅官网。

1.1.1 安装

从 CRAN 安装最新发行版本的最简单方法是安装整个 tidyverse。

install.packages("tidyverse")

由于readxl不是tidyverse核心加载包,使用时仅需加载library(readxl)

或者是从CRAN仅安装readxl;

install.packages("readxl")

从github安装开发版:

# install.packages("devtools")
devtools::install_github("tidyverse/readxl")

1.1.2 用法

readxl 包的核心函数是读取函数read_excel(),该函数能将 Excel 文件数据加载到R中。readxl 包中包含了几个示例文件,我们在接下来的案例中使用。

1.读取

通过readxl_example()查看 readxl 包中自带 xlsx 文件。

library(readxl)
readxl_example()
#>  [1] "clippy.xls"    "clippy.xlsx"   "datasets.xls"  "datasets.xlsx"
#>  [5] "deaths.xls"    "deaths.xlsx"   "geometry.xls"  "geometry.xlsx"
#>  [9] "type-me.xls"   "type-me.xlsx"
readxl_example("clippy.xls")
#> [1] "C:/R/R-4.1.0/library/readxl/extdata/clippy.xls"

需要注意read_excel()可读取 xls 和 xlsx 文件,函数会自动识别。

xls 和 xlsx 的区别: xls 是 excel2003 及以前版本生成的文件格式,而 xlsx 是 excel2007 及以后版本生成的文件格式。xlsx 格式是向下兼容的,可兼容 xls 格式。老旧的业务使用的格式可能是 xls 格式。

xlsx_example <- readxl_example("datasets.xlsx") #返回 datasets.xlsx文件所在路径
dt <- read_excel(xlsx_example)

查看数据

head(dt)
#> # A tibble: 6 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#>          <dbl>       <dbl>        <dbl>       <dbl> <chr>  
#> 1          5.1         3.5          1.4         0.2 setosa 
#> 2          4.9         3            1.4         0.2 setosa 
#> 3          4.7         3.2          1.3         0.2 setosa 
#> 4          4.6         3.1          1.5         0.2 setosa 
#> 5          5           3.6          1.4         0.2 setosa 
#> 6          5.4         3.9          1.7         0.4 setosa

将 Excel 中的数据通过read_excel()读取保存到R中,该对象属于tbl_df类,是 tidyverse 系列的包数据框结构,是对 base R中的data.frame结构的改造,但是兼容data.frame

# 查看dt类
class(dt)
#> [1] "tbl_df"     "tbl"        "data.frame"

# 查看数据类型
str(dt)
#> tibble [150 x 5] (S3: tbl_df/tbl/data.frame)
#>  $ Sepal.Length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
#>  $ Sepal.Width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
#>  $ Petal.Length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
#>  $ Petal.Width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
#>  $ Species     : chr [1:150] "setosa" "setosa" "setosa" "setosa" ...

关于tbl_df类,可以查阅vignette("tibble")

2.指定 sheet 读取

通过函数excel_sheets()查看 Excel 的sheet名称

excel_sheets(xlsx_example)
#> [1] "iris"     "mtcars"   "chickwts" "quakes"

当我们要读取 Excel 文件有多个 sheets 时,通过指定 sheet 参数,读取指定的 sheet,sheet 参数可以 是 sheet 的名称或顺序号。

read_excel(xlsx_example, sheet = "chickwts")
#> # A tibble: 71 x 2
#>   weight feed     
#>    <dbl> <chr>    
#> 1    179 horsebean
#> 2    160 horsebean
#> 3    136 horsebean
#> 4    227 horsebean
#> 5    217 horsebean
#> 6    168 horsebean
#> # ... with 65 more rows
# not run
#read_excel(xlsx_example, sheet = 1)
#read_excel(xlsx_example, sheet = 3)

3.指定读取范围

读取 Excel 文件指定范围。read_excel()中 range 参数接受单元格范围,最简单的表示方式即 Excle 中单元格表示方法,如 range = “D12:F15” or range = “R1C12:R6C15”。

read_excel(xlsx_example, sheet = "iris")
#> # A tibble: 150 x 5
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#>          <dbl>       <dbl>        <dbl>       <dbl> <chr>  
#> 1          5.1         3.5          1.4         0.2 setosa 
#> 2          4.9         3            1.4         0.2 setosa 
#> 3          4.7         3.2          1.3         0.2 setosa 
#> 4          4.6         3.1          1.5         0.2 setosa 
#> 5          5           3.6          1.4         0.2 setosa 
#> 6          5.4         3.9          1.7         0.4 setosa 
#> # ... with 144 more rows

dt1 <- read_excel(xlsx_example, sheet = "iris",range = 'a1:e6')

dt2 <- read_excel(xlsx_example, sheet = "iris",range = 'R1C1:R6C5')

# dt1 dt2 是否相等
identical(dt1,dt2)
#> [1] TRUE

4.read_excel参数

readxl::read_excel 参数如下,请?read_excel()查看参数。

read_excel(path, sheet = NULL, range = NULL, col_names = TRUE,
  col_types = NULL, na = "", trim_ws = TRUE, skip = 0,
  n_max = Inf, guess_max = min(1000, n_max),
  progress = readxl_progress(), .name_repair = "unique")
read_excel参数 解释
path xls或xlsx文件的路径
sheet 默认是第一个sheet,可以是数字或sheet的名称
range Excel中表示范围的字符,或者通过cell_类方法指定
col_name 默认为TRUE,用第一行做列名;或者用默认名称,或者指定列名
col_types 默认为NULL,猜测各列类型,可指定各列的类型
trim_ws 默认去掉表头字段中两边的空格
skip 读取之前要跳过的行数,默认为空
n_max 读取的最大行数
guess_max 猜测列类型的最大行数,默认为1000
progress 读取过程是否显示进度
.name_repair 自动处理列名,避免列名为空以及列名重复

col_types 参数个人觉得比较重要,可以指定列的类型,可以避免一些错误。可用选项:“skip,” “guess,” “logical,” “numeric,” “date,” “text” or “list”。

.name_repair 参数能自动避免重复字段,可避免手工 Excel 出现字段名不唯一的情况。

1.1.3 批量读取

实际工作中,某文件夹下有相同格式的 Excel 文件(sheet名称以及列字段相同),想要合并全部 Excel 数据,熟悉 Excel 的可以通过 Excel 的power query的获取数据完成合并,那么在R中该如何实现呢?

示例:

文件夹内 excel 文件

#> data/read-write/
#> +-- a.xlsx
#> +-- b.xlsx
#> +-- PivotTable.xlsx
#> \-- 批量读写.xlsx

将文件夹『data/read-write』里以 a-z 开头的 xlsx 文件合并读取,R代码如下:

  • base R

不借助R包,使用 base R 实现

allfiles <- list.files(path = 'data/read-write/',pattern = '^[a-z].xlsx$',full.names = TRUE)
datalist <- lapply(allfiles,readxl::read_excel)
do.call(rbind,datalist)
#> # A tibble: 6 x 2
#>    name   num
#>   <dbl> <dbl>
#> 1     1     1
#> 2     2     2
#> 3     3     3
#> 4     1     1
#> 5     2     2
#> 6     3     3
  • purrr

使用 purrr 包合并读取

allfiles <- list.files(path = './data/read-write/',pattern = '^[a-z].xlsx$',full.names = T)

purrr::map_dfr(allfiles,read_excel)
#> # A tibble: 6 x 2
#>    name   num
#>   <dbl> <dbl>
#> 1     1     1
#> 2     2     2
#> 3     3     3
#> 4     1     1
#> 5     2     2
#> 6     3     3

list.files()函数按照规则返回某文件目录下的全部文件。关于R语言中文件系统操作可以查看章节R语言文件系统操作

1.1.4 批量输出

我们按照一定条件拆解数据集,分别输出,代码如下:

library(tidyverse)
library(readxl)

dt <- read_xlsx(path = './data/read-write/批量读写.xlsx')

dt %>% 
  group_by(name) %>% 
  group_walk(~ write.csv(.x,file = file.path('data/read-write',paste0(.y$name,'.csv'))))
list.files(path = 'data/read-write/')
#> [1] "a.csv"            "a.xlsx"           "b.csv"            "b.xlsx"          
#> [5] "d.csv"            "Id-card-data.csv" "PivotTable.xlsx"  "批量读写.xlsx"

暂时不用理解批量读取和输出的代码具体含义,可以先记住用法。