专栏首页优雅R「Geek-r」数据导入

「Geek-r」数据导入

本部分内容是我写的 R book 的数据导入部分,写了好久了。。。断断续续的,只完成了一半的内容吧。已经写的的内容可以通过原文阅读。

在掌握一定的 R 编程技能后,我们开始迈入数据分析的殿堂。大部分数据分析事务的数据都不是通过 R 创建,而是来自于各种数据收集软硬件、渠道,包括 Excel、网络等。本章聚焦于如何将数据导入 R 中以便于开始数据分析。对于本章的内容,读者既可以系统地从头到尾深入阅读学习,也可以根据自己实际工作需要或时间限制选择一些重点或感兴趣内容进行掌握。

本章的重点内容包括符号分隔文件、Excel 文件、JSON 文件以及 R 支持的数据格式 RData 和 RDS,其他格式的数据将放到本章【常见问题与方案】一节作为补充介绍。

3.1 符号分隔文件

符号分隔文件是最最常用的数据文件格式,知道如何导入它是读者的必备技能。这里的符号泛指一切可以用作数据内容分隔的符号,常见的包括逗号(,),制表符(\t),我们常称它们为 CSV 文件和 TSV 文件。

3.1.1 CSV

CSV 文件常以 .csv 作为文件拓展名,比如接下来我们会导入的 mtcars.csv。注意,文件拓展名并不会影响文件本身的内容,它只是用来方便帮助人们快速的了解内容格式,另外支持其他一些程序的自动解读(在你的计算机上,不同的文件拓展名系统软件可以会对它们使用不同的图标,如 Word 文档和 PPT)。

一般规整的数据以行作为观测,列作为记录(变量、域),如一个班级同学的成绩。

student,chinese,math,english
stu1,99,100,98
stu2,60,50,88

R 内置了 read.table() 函数用于便捷导入各类分隔符的文件。下面我们直接将这个成绩记录信息以文本的形式传入,结果会返回一个数据框:

stu <- read.table(text = "
student,chinese,math,english
stu1,99,100,98
stu2,60,50,88
", header = TRUE, sep = ",")
stu
#>   student chinese math english
#> 1    stu1      99  100      98
#> 2    stu2      60   50      88
class(stu)
#> [1] "data.frame"

实际上要处理的数据并不会这么的少,一般会以文件的形式存储在计算机磁盘中。下面我们依旧使用 read.table() 函数完成 CSV 文件数据的导入。

cars <- read.table(file = "data/data-import/mtcars.csv", header = TRUE, sep = ",")

操作完成了,我们检查下头几行:

head(cars)
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

除了使用 read.table(),我们还可以使用内置的 read.csv() 函数完成 CSV 文件的读入。与 read.table() 不同的时,我们无需再指定分隔符,因为该函数本身就是为了 CSV 文件设计的。另外函数默认将 header 选项设定为 TRUE,即有列名,所以我们也无需指定它,因而读取操作就被简化了:

cars2 <- read.csv(file = "data/data-import/mtcars.csv")
head(cars2)
#>    mpg cyl disp  hp drat    wt  qsec vs am gear carb
#> 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
#> 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
#> 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
#> 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
#> 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
#> 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

上述的读取操作基于 R 内置的函数实现,无需载入任何其他三方包就可以完成数据的读入,这在针对小型数据(集)或者计算机条件受限时(无法安装和使用三方包)非常有用。在这种常规以符号分隔的文件数据读取方面,我必须提及 2 个三方包:readrdata.table。它们都能以极快的速度读取大内存数据,推荐读者作为常规导入操作的解决方案。

**tidyverse**[1] 是 R 语言大神 Hadley[2](以 ggplot2 作者闻名于世) 组织构建的一整套数据分析生态系统,包括读入、处理、建模与可视化等, **readr**[3] 包是 tidyverse 的一部分,用于完成数据的导入工作。

**data.table**[4] 包以 R 社区最快的数据读取和处理操作而著名,它主要是提供了一个增强版的数据框 data.table

根据 readr 包官方文档介绍,readr 包通常比 data.table 包慢大概 1.2~2 倍左右。不过它们各有特点,readr 包被设计用于更为常规的数据读取操作,而 data.table 的目标则是尽量的快。

为了体现上述两个包和内置函数的差别,这里我们构造一个较大的 CSV 文件进行简单的测试:

huge_car <- cars[rep(1:32, 10000), ]

把这个数据先保存下来,然后再利用不同的工具进行导入。

temp_csv <- tempfile(fileext = ".csv")
readr::write_csv(huge_car, path = temp_csv)

现在我们分别使用 system.time() 测试下 R 内置的 read.csv() 函数与 readr 提供的 read_csv() 以及 data.table 提供的 fread() 的读取效率。

time1 <- system.time(
  z1 <- read.csv(temp_csv)
)
time1
#>  用户  系统  流逝 
#> 0.921 0.025 0.947
library(readr)

time2 <- system.time(
  z2 <-  read_csv(temp_csv)
)
time2
#>  用户  系统  流逝 
#> 0.311 0.023 0.346
library(data.table)

time3 <- system.time(
  z3 <- fread(temp_csv)
)
time3
#>  用户  系统  流逝 
#> 0.050 0.007 0.056

上面我们使用了 320000 行数据进行测试,在我的计算机上,内置的函数 read.csv() 总共花费了 0.947s,readrread_csv() 花费了 0.346s,而 data.tablefread() 仅用了 0.056s 左右。好的、适合的工具可以帮助我们极大地提升工作效率

如果我们进一步观察几种不同方式导入的数据格式,就会发现它们有些不太相同。

z1
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
#> 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#> 11 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#> 12 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
#> 13 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
#> 14 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
#> 15 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
#> 16 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
#> 17 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
#> 18 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 19 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 20 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 21 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> 22 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
#> 23 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
#> 24 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
#> 25 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
#> 26 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> 27 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> 28 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> 29 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> 30 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> 31 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#> 32 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
#> 33 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 34 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 35 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 36 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 37 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 38 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 39 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 40 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 41 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
#> 42 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#> 43 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#> 44 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
#> 45 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
#> 46 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
#> 47 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
#> 48 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
#> 49 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
#> 50 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 51 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 52 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 53 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> 54 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
#> 55 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
#> 56 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
#> 57 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
#> 58 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> 59 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> 60 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> 61 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> 62 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> 63 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#> 64 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
#> 65 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 66 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 67 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 68 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 69 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 70 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 71 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 72 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 73 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
#> 74 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#> 75 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#> 76 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
#> 77 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
#> 78 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
#> 79 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
#> 80 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
#> 81 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
#> 82 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 83 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 84 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 85 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> 86 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
#> 87 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
#> 88 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
#> 89 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
#> 90 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#>  [ reached 'max' / getOption("max.print") -- omitted 319910 rows ]
z2
#> # A tibble: 320,000 x 11
#>      mpg   cyl  disp    hp  drat    wt  qsec    vs
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1  21       6  160    110  3.9   2.62  16.5     0
#>  2  21       6  160    110  3.9   2.88  17.0     0
#>  3  22.8     4  108     93  3.85  2.32  18.6     1
#>  4  21.4     6  258    110  3.08  3.22  19.4     1
#>  5  18.7     8  360    175  3.15  3.44  17.0     0
#>  6  18.1     6  225    105  2.76  3.46  20.2     1
#>  7  14.3     8  360    245  3.21  3.57  15.8     0
#>  8  24.4     4  147.    62  3.69  3.19  20       1
#>  9  22.8     4  141.    95  3.92  3.15  22.9     1
#> 10  19.2     6  168.   123  3.92  3.44  18.3     1
#> # … with 319,990 more rows, and 3 more variables:
#> #   am <dbl>, gear <dbl>, carb <dbl>
z3
#>          mpg cyl  disp  hp drat    wt  qsec vs am gear
#>      1: 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
#>      2: 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
#>      3: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4
#>      4: 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3
#>      5: 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3
#>     ---                                               
#> 319996: 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5
#> 319997: 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5
#> 319998: 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5
#> 319999: 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5
#> 320000: 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4
#>         carb
#>      1:    4
#>      2:    4
#>      3:    1
#>      4:    1
#>      5:    2
#>     ---     
#> 319996:    2
#> 319997:    4
#> 319998:    6
#> 319999:    8
#> 320000:    2

这个所谓的不同与结构中存储的数据信息无关,而是在不同的设计上。我们检查一下它们的类属性:

class(z1)
#> [1] "data.frame"
class(z2)
#> [1] "spec_tbl_df" "tbl_df"      "tbl"        
#> [4] "data.frame"
class(z3)
#> [1] "data.table" "data.frame"

不难看到这 3 个对象存在共有的类名 data.frame。我们使用内置函数读入数据仅包含该类名,而后两者还存在其他的类名,这是因为后两者继承了 data.frame。简单地说,后两者是增强版的 data.frame,它们赋予了不同于 R 内置数据框的特性,读者可以观察到的最明显的区别就是它们打印信息的方式不同。

通常地说,我们将对象 z2 称为 tibble,因为它是由 **tibble**[5] 包创建的类,是 tidyverse 系列包的数据结构基础,设计者称它为现代的 data.frame,在基础的使用方式上与 data.frame 并无不同,读者可以通过官方文档阅读更为详细的介绍。

对象 z3 则常被称为 data.table,因为它的类名和包名都是 data.table.

tibbledata.table 都有一系列强大高效的数据处理方法和操作,它们将在第 4[6] 章进行介绍。

3.1.2 TSV 与其他 CSV 变体

另一种流行的数据存储格式是 TSV,与 CSV 唯一不同的是 TSV 使用制表符 \t 作为内容的分隔符。TSV 文件除了以 .tsv 作为文件拓展名,也常用 .txt 作为文件拓展名(并不是所有的 .txt 文件都是以制表符分隔)。

通过将 read.table() 函数中的 sep 参数设定为制表符,我们可以轻松完成该格式文件内容的读取:

mt <- read.table("data/data-import/mtcars.tsv", sep = "\t", header = TRUE)
mt
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
#> 10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#> 11 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#> 12 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
#> 13 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
#> 14 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
#> 15 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
#> 16 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
#> 17 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
#> 18 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 19 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 20 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 21 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> 22 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
#> 23 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
#> 24 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
#> 25 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
#> 26 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> 27 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> 28 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> 29 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> 30 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> 31 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#> 32 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

readr 包提供了一系列的 read_*() 函数,方便用户将常见数据文件导入为 tibble

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

使用 data.table 则更为轻松,因为所有分隔格式的数据都可以通过 fread() 读取完成:

mt3 <- fread("data/data-import/mtcars.tsv")
mt3
#>      mpg cyl  disp  hp drat    wt  qsec vs am gear
#>  1: 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4
#>  2: 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4
#>  3: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4
#>  4: 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3
#>  5: 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3
#>  6: 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3
#>  7: 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3
#>  8: 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4
#>  9: 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4
#> 10: 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4
#> 11: 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4
#> 12: 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3
#> 13: 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3
#> 14: 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3
#> 15: 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3
#> 16: 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3
#> 17: 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3
#> 18: 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4
#> 19: 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4
#> 20: 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4
#> 21: 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3
#> 22: 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3
#> 23: 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3
#> 24: 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3
#> 25: 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3
#> 26: 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4
#> 27: 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5
#> 28: 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5
#> 29: 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5
#> 30: 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5
#> 31: 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5
#> 32: 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4
#>      mpg cyl  disp  hp drat    wt  qsec vs am gear
#>     carb
#>  1:    4
#>  2:    4
#>  3:    1
#>  4:    1
#>  5:    2
#>  6:    1
#>  7:    4
#>  8:    2
#>  9:    2
#> 10:    4
#> 11:    4
#> 12:    3
#> 13:    3
#> 14:    3
#> 15:    4
#> 16:    4
#> 17:    4
#> 18:    1
#> 19:    2
#> 20:    1
#> 21:    1
#> 22:    2
#> 23:    2
#> 24:    4
#> 25:    2
#> 26:    1
#> 27:    2
#> 28:    2
#> 29:    4
#> 30:    6
#> 31:    8
#> 32:    2
#>     carb

为什么 fread() 没有设置分隔符却可以导入 CSV 和 TSV 文件?其中的巧妙在于该函数的内部会自动检测数据文件内的分隔符号。

通过查看该函数的参数,我们可以看到 sep = "auto",这个参数我们可以人为指定,以适应不同的需求场景。

args(fread)
#> function (input = "", file = NULL, text = NULL, cmd = NULL, sep = "auto", 
#>     sep2 = "auto", dec = ".", quote = "\"", nrows = Inf, header = "auto", 
#>     na.strings = getOption("datatable.na.strings", "NA"), stringsAsFactors = FALSE, 
#>     verbose = getOption("datatable.verbose", FALSE), skip = "__auto__", 
#>     select = NULL, drop = NULL, colClasses = NULL, integer64 = getOption("datatable.integer64", 
#>         "integer64"), col.names, check.names = FALSE, encoding = "unknown", 
#>     strip.white = TRUE, fill = FALSE, blank.lines.skip = FALSE, 
#>     key = NULL, index = NULL, showProgress = getOption("datatable.showProgress", 
#>         interactive()), data.table = getOption("datatable.fread.datatable", 
#>         TRUE), nThread = getDTthreads(verbose), logical01 = getOption("datatable.logical01", 
#>         FALSE), keepLeadingZeros = getOption("datatable.keepLeadingZeros", 
#>         FALSE), yaml = FALSE, autostart = NA, tmpdir = tempdir()) 
#> NULL

上面展示出 fread() 存在众多的参数设置。R 的易用与友好在于此,众多 R 包提供的函数大多已经为用户恰当地设置好了默认选项,用户无需经过繁琐的操作即可快速获取所需的结果。

在学习了如何导入 TSV 文件后,我们应该能够归纳出 CSV、TSV 本质上是一类数据格式文件。例如,我们也可以使用分号 ;(西方不少国家的逗号分隔文件就是以分号分隔的文件)。我们统一以 CSV 作为代表,将其他类似格式文件称为 CSV 变体。

3.2 Excel

Excel 是知名的微软 Office 套件之一,提供了日常的表格数据处理方案。尽管大多数数据分析人员不会产生和不想处理 Excel 文件,但由于它随着微软系统的流行而被广泛使用,因此读入 Excel 中的数据成为数据处理无法避免的日常工作任务之一。

R 中有诸多拓展包可以导入 Excel 中的数据,其中最为推荐的就是本部分介绍的 **readxl**[7] 包。

使用该包,导入 Excel 中的数据可以像读入 CSV 文件一样简单。

library(readxl)
mt_excel <- read_excel("data/data-import/mtcars.xlsx")
head(mt_excel)
#> # A tibble: 6 x 11
#>     mpg   cyl  disp    hp  drat    wt  qsec    vs    am
#>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1  21       6   160   110  3.9   2.62  16.5     0     1
#> 2  21       6   160   110  3.9   2.88  17.0     0     1
#> 3  22.8     4   108    93  3.85  2.32  18.6     1     1
#> 4  21.4     6   258   110  3.08  3.22  19.4     1     0
#> 5  18.7     8   360   175  3.15  3.44  17.0     0     0
#> 6  18.1     6   225   105  2.76  3.46  20.2     1     0
#> # … with 2 more variables: gear <dbl>, carb <dbl>

read_excel() 同时支持 .xlsxlsx 两者文件格式。

Excel 文件支持多个表格(Sheet),这种情况下默认第 1 个 Sheet 的内容会被读入。通过简单的设置,读者也可以轻松导入任意 Sheet 的内容。

下面通过 readxl 包的官方示例展示这一过程。

我们先查看下该包提供的示例数据:

readxl_example()
#>  [1] "clippy.xls"    "clippy.xlsx"   "datasets.xls" 
#>  [4] "datasets.xlsx" "deaths.xls"    "deaths.xlsx"  
#>  [7] "geometry.xls"  "geometry.xlsx" "type-me.xls"  
#> [10] "type-me.xlsx"

选一个文件并查看其所在的路径:

readxl_example("datasets.xlsx")
#> [1] "/Users/wsx/R_Library/readxl/extdata/datasets.xlsx"
# 将路径保存备用
excel_path <- readxl_example("datasets.xlsx")

如果将路径传入 excel_sheets() 函数,读者可以获取文件中存在的 Sheets。

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

然后依旧是使用 read_excel() 函数,设定想要读入的 Sheet 名字即可。

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

关于函数的更多用法读者可以通过 ?read_excel() 查看。

有时候人们会在同一个 Excel Sheet 中放置多个表格信息,这种情况无法通过简单地使用 readxl 包读入数据。只要数据是有规律的,读者可以尝试下通过 **tidycells**[8] 包导入数据。

tidycells 包示例数据

图 3.1: tidycells 包示例数据格式

具体的使用请读者参照 README[9] 进行学习。

参考资料

[1]

tidyverse: https://github.com/tidyverse/

[2]

Hadley: https://github.com/hadley

[3]

readr: https://github.com/tidyverse/readr

[4]

data.table: https://github.com/Rdatatable/data.table

[5]

tibble: https://github.com/tidyverse/tibble

[6]

4: https://shixiangwang.gitee.io/geek-r-tutorial/clean.html#clean

[7]

readxl: https://github.com/tidyverse/readxl

[8]

tidycells: https://github.com/r-rudra/tidycells

[9]

README: https://github.com/r-rudra/tidycells/blob/master/README.md

本文分享自微信公众号 - 优雅R(elegant-r),作者:王诗翔

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • TidyFriday 每天 5 分钟,轻轻松松上手 R 语言(六)数据读取与保存

    我们最先要了解的是我们的工作目录,当文件在当前目录下时我们输入文件名即可, 没有在当前目录我们就要输入数据文件的绝对路径。

    王诗翔呀
  • 两天研习Python基础(八) 序列、集合以及字典数据类型

    我们在前面的文章中已经看到过字符串、列表等序列类型。元组是另外一种序列类型。这一章我们学习更多关于字符串、元组、字典和集合的操作。

    王诗翔呀
  • FancyHeatmap,支持输出嵌入网站了!

    FancyHeatmap,是我给TBtools中“卡通式热图”命的名字。前述,在公众号上,我已经推出了这个功能相关的新手教程。在后续,我也发现有不少人已经应用:

    王诗翔呀
  • 不应面向对象地针对业务行为建立模型!

    在过去的几年中,我看到许多项目将几乎任何类型的业务需求都喜欢建立与需求原因无关的技术对象模型(后面可能简称对象模型)。在很多情况下,针对技术对象建立业务需求模型...

    小小科学家
  • 经典二叉树

    完全二叉树特点: 1 叶子节点只能出现在最下面两层 2 最下层的叶子一定集中在左部连续位置 3 倒数第二层,如果有叶子节点,一定都集中在右边 4 如果节点度为1...

    用户1154259
  • 畅游数据库性能优化过程简析(下)

    经过周末两天的折腾,在大家的帮助下最终将用户 DB 的性能峰值由最初的不到 8W 的 QPS + TPS 提升至 17W,心情也由最初的忐忑过渡到现在的平静,现...

    musazhang
  • 手把手教你使用Python实现常用的假设检验 !

    比如:两个样本方差比服从F分布,区间估计就采用F分布计算临界值(从而得出置信区间),最终采用F检验。

    我被狗咬了
  • 介绍一套BPM系统应该有的功能

    近几年IT行业各种IT应用发展十分迅猛,企业和公司内部信息管理系统越来越多。由于一些原因,这些系统的信息资源管理分散、共享困难、由此造成了一些信息孤岛。...

    程序源代码
  • 【逆向&编程实战】Metasploit安卓载荷运行流程分析_复现meterpreter模块接管shell

    MainActivity在向MainService类的startService方法传入了Context后立刻结束掉了当前类

    重生信息安全
  • 深入理解MySQL 5.7 GTID系列(五) gtid_executed&amp;amp;gtid_purged什么时候更新

    本节将集中讨论下面三种GTID更新的时机,这部分相当重要,后面的故障案列会和这节有关。下面先来看一下他们的定义:

    wubx

扫码关注云+社区

领取腾讯云代金券