R 數(shù)據(jù)處理(二十一)— readxl

前言

我們進(jìn)行數(shù)據(jù)處理時,有時還會遇到一種常見的文件:Microsoft Office Excel 工作表的格式。

R 中有許多用于讀取 Excel 文件的包,如 gdata, xlsx, xlsReadWrite。

而我們要介紹的是 tidyverse 中的又一個包 readxl

與它們相比,readxl 沒有任何外部依賴性,因此很容易在所有操作系統(tǒng)上安裝和使用。它的設(shè)計是為了處理表格數(shù)據(jù)

readxl 支持舊版的 .xls 格式和現(xiàn)代的基于 xml.xlsx 格式

在它的底層使用 libxls C 庫來支持 .xls 格式,使用 RapidXML C++ 庫來解析 .xlsx。

安裝

最簡單的就是直接安裝 tidyverse

install.packages("tidyverse")

如果你只想安裝 readxl

install.packages("readxl")

或者從 GitHub 上安裝開發(fā)者版本

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

使用

1. 導(dǎo)入

readxl 不是 tidyverse 的核心包,需要顯式導(dǎo)入

library(readxl)

2. 讀取表

readxl 中包含一些示例文件,我們可以使用不帶參數(shù)的 readxl_example() 來列出它們,或者傳入示例文件名來獲取文件的路徑

> readxl_example()
 [1] "clippy.xls"    "clippy.xlsx"   "datasets.xls"  "datasets.xlsx" "deaths.xls"    "deaths.xlsx"  
 [7] "geometry.xls"  "geometry.xlsx" "type-me.xls"   "type-me.xlsx"
 
> readxl_example("clippy.xls")
[1] "/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readxl/extdata/clippy.xls"

然后使用 read_excel() 讀取 xlsxlsx 文件,會自動從擴(kuò)展名中檢測文件格式

# 讀取 xlsx 文件
> readxl_example("datasets.xlsx") %>% read_excel()
# 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 
 7          4.6         3.4          1.4         0.3 setosa 
 8          5           3.4          1.5         0.2 setosa 
 9          4.4         2.9          1.4         0.2 setosa 
10          4.9         3.1          1.5         0.1 setosa 
# … with 140 more rows

# 讀取 xls 文件
> readxl_example("datasets.xls") %>% read_excel()
# 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 
 7          4.6         3.4          1.4         0.3 setosa 
 8          5           3.4          1.5         0.2 setosa 
 9          4.4         2.9          1.4         0.2 setosa 
10          4.9         3.1          1.5         0.1 setosa 
# … with 140 more rows

read_excel 默認(rèn)會把第一個表讀取進(jìn)來,但是一個 Excel 文件可以包含多個表名,那么該如何讀取其他表呢?

我們可以通過設(shè)置 sheet 參數(shù)來指定需要從 Excel 文件中讀取的表名。例如 datasets.xlsx 文件中有一個名為 mtcars 的表

> readxl_example("datasets.xlsx") %>% read_excel(sheet = 'mtcars')
# A tibble: 32 x 11                                                                                  
     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
 2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
 3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
 4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
 5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
 6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
 7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
 8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
 9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
# … with 22 more rows

那我是不是只能通過打開 Excel 文件來獲知所有表名呢?

readxl 已經(jīng)幫我們做到了,它提供了 excel_sheets() 函數(shù),能夠獲取所有的表名

> readxl_example("datasets.xlsx") %>% excel_sheets()
[1] "iris"     "mtcars"   "chickwts" "quakes"

既然獲取到了所有的表名,那我能不能通過傳入表名的索引來獲取對應(yīng)表的數(shù)據(jù)呢?

> readxl_example("datasets.xlsx") %>% read_excel(sheet = 2)
# A tibble: 32 x 11                                                                                  
     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
 2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
 3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
 4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
 5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
 6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
 7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
 8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
 9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
# … with 22 more rows

完全沒問題。

3. 設(shè)置讀取范圍

有時候我們的 Excel 表格并不是完完全全矩陣格式,或者同一個表內(nèi)包含了許多的表。

那么通過設(shè)置讀取范圍,能夠準(zhǔn)確快速的獲取到我們想要的信息

  • n_max 參數(shù)設(shè)置讀取的行數(shù)
> readxl_example("datasets.xls") %>% read_excel(n_max = 3)
# A tibble: 3 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
  • range 參數(shù)設(shè)置矩形的范圍
> readxl_example("datasets.xls") %>% read_excel(range = "C1:E4")
# A tibble: 3 x 3                                                                                    
  Petal.Length Petal.Width Species
         <dbl>       <dbl> <chr>  
1          1.4         0.2 setosa 
2          1.4         0.2 setosa 
3          1.3         0.2 setosa 

注意:我們指定了 rangeC1-E4 的矩形范圍,其中 E4 并不包含在范圍之內(nèi)

也可以為 range 指定行或列的讀取范圍

> readxl_example("datasets.xls") %>% read_excel(range = cell_rows(1:4))
# A tibble: 3 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

> readxl_example("datasets.xls") %>% read_excel(range = cell_cols('B:D'))
# A tibble: 150 x 3                                                                                  
   Sepal.Width Petal.Length Petal.Width
         <dbl>        <dbl>       <dbl>
 1         3.5          1.4         0.2
 2         3            1.4         0.2
 3         3.2          1.3         0.2
 4         3.1          1.5         0.2
 5         3.6          1.4         0.2
 6         3.9          1.7         0.4
 7         3.4          1.4         0.3
 8         3.4          1.5         0.2
 9         2.9          1.4         0.2
10         3.1          1.5         0.1
# … with 140 more rows

> readxl_example("datasets.xls") %>% read_excel(range = cell_cols(2:4))
# A tibble: 150 x 3                                                                                  
   Sepal.Width Petal.Length Petal.Width
         <dbl>        <dbl>       <dbl>
 1         3.5          1.4         0.2
 2         3            1.4         0.2
 3         3.2          1.3         0.2
 4         3.1          1.5         0.2
 5         3.6          1.4         0.2
 6         3.9          1.7         0.4
 7         3.4          1.4         0.3
 8         3.4          1.5         0.2
 9         2.9          1.4         0.2
10         3.1          1.5         0.1
# … with 140 more rows

range 指定表格以及范圍

> readxl_example("datasets.xls") %>% read_excel(range = "mtcars!B1:D5")
# A tibble: 4 x 3                                                                                    
    cyl  disp    hp
  <dbl> <dbl> <dbl>
1     6   160   110
2     6   160   110
3     4   108    93
4     6   258   110

注意:請注意范圍選取的開區(qū)間閉區(qū)間

  • na 參數(shù)將空白之外的字符設(shè)置為 NA
> readxl_example("datasets.xls") %>% read_excel(na = "setosa")
# 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 NA     
 2          4.9         3            1.4         0.2 NA     
 3          4.7         3.2          1.3         0.2 NA     
 4          4.6         3.1          1.5         0.2 NA     
 5          5           3.6          1.4         0.2 NA     
 6          5.4         3.9          1.7         0.4 NA     
 7          4.6         3.4          1.4         0.3 NA     
 8          5           3.4          1.5         0.2 NA     
 9          4.4         2.9          1.4         0.2 NA     
10          4.9         3.1          1.5         0.1 NA     
# … with 140 more rows
  • skip 參數(shù)設(shè)置在讀取之前需要跳過的行數(shù),如果設(shè)置了 range,則不會發(fā)揮作用
> readxl_example("datasets.xls") %>% read_excel(skip = 1, sheet = "chickwts") %>% head(3)
# A tibble: 3 x 2                                                                                    
  `179` horsebean
  <dbl> <chr>    
1   160 horsebean
2   136 horsebean
3   227 horsebean

4. 設(shè)置表名

read_excel 默認(rèn)將第一行設(shè)置為表頭,即 col_names=TRUE。如果 col_names=FALSE 則不會將第一行設(shè)置為表頭。

> readxl_example("datasets.xls") %>% read_excel(skip = 1, sheet = "chickwts", col_names = FALSE)
New names:                                                                                           
* `` -> ...1
* `` -> ...2
# A tibble: 71 x 2
    ...1 ...2     
   <dbl> <chr>    
 1   179 horsebean
 2   160 horsebean
 3   136 horsebean
 4   227 horsebean
 5   217 horsebean
 6   168 horsebean
 7   108 horsebean
 8   124 horsebean
 9   143 horsebean
10   140 horsebean
# … with 61 more rows

同時 col_names 參數(shù)也可以接受一個字符串向量,代表我們需要設(shè)置的列名

> readxl_example("datasets.xls") %>% read_excel(skip = 1, 
          sheet = "chickwts", 
          col_names = c("chick_weight", "chick_ate_this"))
# A tibble: 71 x 2                                                                                   
   chick_weight chick_ate_this
          <dbl> <chr>         
 1          179 horsebean     
 2          160 horsebean     
 3          136 horsebean     
 4          227 horsebean     
 5          217 horsebean     
 6          168 horsebean     
 7          108 horsebean     
 8          124 horsebean     
 9          143 horsebean     
10          140 horsebean     
# … with 61 more rows

但是總是這樣手動設(shè)置列名是很麻煩的,特別是一些不符合 R 變量語法的列名

readxl 提供 .name_repair 參數(shù),該參數(shù)可以控制如何檢查或修復(fù)列名

該參數(shù)在 read_excel(), read_xls()read_xlsx() 中的作用與 tibble::tibble()tibble::as_tibble() 中一樣

默認(rèn)情況下 .name_repair = "unique",即只要保證每列的列名唯一即可,而不做其他檢查

如果設(shè)置 .name_repair = "universal",會將列名設(shè)置為符合語法規(guī)則的名稱,確保它們不包含任何禁止使用的字符或保留字

設(shè)置為 unique 時,列名可以包含空格,如果為 universal 會用 . 替換空格

> readxl_example("deaths.xlsx") %>%
+     read_excel(range = "arts!A5:F8")
# A tibble: 3 x 6                                                                                    
  Name          Profession   Age `Has kids` `Date of birth`     `Date of death`    
  <chr>         <chr>      <dbl> <lgl>      <dttm>              <dttm>             
1 David Bowie   musician      69 TRUE       1947-01-08 00:00:00 2016-01-10 00:00:00
2 Carrie Fisher actor         60 TRUE       1956-10-21 00:00:00 2016-12-27 00:00:00
3 Chuck Berry   musician      90 TRUE       1926-10-18 00:00:00 2017-03-18 00:00:00

# 用 . 替換空格
> readxl_example("deaths.xlsx") %>%
+     read_excel(range = "arts!A5:F8", .name_repair = "universal")
New names:                                                                                           
* `Has kids` -> Has.kids
* `Date of birth` -> Date.of.birth
* `Date of death` -> Date.of.death
# A tibble: 3 x 6
  Name          Profession   Age Has.kids Date.of.birth       Date.of.death      
  <chr>         <chr>      <dbl> <lgl>    <dttm>              <dttm>             
1 David Bowie   musician      69 TRUE     1947-01-08 00:00:00 2016-01-10 00:00:00
2 Carrie Fisher actor         60 TRUE     1956-10-21 00:00:00 2016-12-27 00:00:00
3 Chuck Berry   musician      90 TRUE     1926-10-18 00:00:00 2017-03-18 00:00:00

除此之外 .name_repair 參數(shù)還可以設(shè)置為函數(shù)

# 傳遞函數(shù)
> readxl_example("clippy.xlsx") %>%
+     read_excel(.name_repair=toupper)
# A tibble: 4 x 2                                                                                    
  NAME                 VALUE    
  <chr>                <chr>    
1 Name                 Clippy   
2 Species              paperclip
3 Approx date of death 39083    
4 Weight in grams      0.9

# 自定義函數(shù)
> readxl_example("datasets.xlsx") %>%
+     read_excel(n_max = 3, .name_repair = function(x) tolower(gsub("[.]", "_", x)))
# A tibble: 3 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 
# purrr 風(fēng)格的匿名函數(shù),只能在 purrr 環(huán)境下使用
> readxl_example("datasets.xlsx") %>%
+     read_excel(n_max = 3, sheet = 'chickwts', .name_repair = ~ substr(.x, start = 1, stop = 3))
# A tibble: 3 x 2                                                                                    
    wei fee      
  <dbl> <chr>    
1   179 horsebean
2   160 horsebean
3   136 horsebean

對于 purrr 風(fēng)格的匿名函數(shù),我們可以看看下面的例子會更好理解

> f <- as_function(~ .x + 1)
> f(10)
[1] 11
> 
> g <- as_function(~ -1 * .)
> g(4)
[1] -4
> 
> h <- as_function(~ .x - .y)
> h(6, 3)
[1] 3
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容