前言
前面讲过了 R
自带的读取矩阵型数据的方法,如 read.csv
,read.table
等。
下面我要介绍的是 tidyverse
中的 readr
包提供的读取矩阵型数据的方式
readr
的目标是提供一种快速友好的方式来读取矩阵型数据,如 csv
, tsv
和 fwf
等。
使用
1. 导入包
library(tidyverse)
函数
readr
支持 7
种文件格式,对应于 7
个 read_
开头的函数
-
-
read_csv()
:CSV
文件
-
-
-
read_csv2()
: 分号;
分隔文件
-
-
-
read_tsv()
:tab
分隔文件
-
-
-
read_delim()
: 一般带分隔符的文件
-
-
-
read_fwf()
: 固定宽度的文件
-
-
-
read_table()
: 表格文件,列之间用空格隔开
-
-
-
read_log()
:web
日志文件
-
通常只要提供文件的路径就可以读取文件,比如读取示例文件
> mtcars <- read_csv(readr_example("mtcars.csv"))
─ Column specification ────────────────────────────────────────
cols(
mpg = col_double(),
cyl = col_double(),
disp = col_double(),
hp = col_double(),
drat = col_double(),
wt = col_double(),
qsec = col_double(),
vs = col_double(),
am = col_double(),
gear = col_double(),
carb = col_double()
)
当你使用 read_csv
时,将会打印每列的列名以及类型,函数自动推断数据的类型
当然在读取文件时,你也可以为每列指定类型
mtcars <- read_csv(readr_example("mtcars.csv"), col_types =
cols(
mpg = col_double(),
cyl = col_integer(),
disp = col_double(),
hp = col_integer(),
drat = col_double(),
vs = col_integer(),
wt = col_double(),
qsec = col_double(),
am = col_integer(),
gear = col_integer(),
carb = col_integer()
)
)
你也可以提供一个内联的 CSV
文件
read_csv("a,b,c
1,2,3
4,5,6")
在这两种读取方式中,都是默认将第一行作为列名。当然,你也可以调整这种模式:
-
当你的文件前几行是数据的描绘信息,并不是你想要的,你可以使用
skip = n
跳过前n
行。或者,使用
comment = "#"
删除所有以#
开头的行
> read_csv("The first line of metadata
+ The second line of metadata
+ x,y,z
+ 1,2,3", skip = 2)
# A tibble: 1 x 3
x y z
1 1 2 3
> read_csv("# A comment I want to skip
+ x,y,z
+ 1,2,3", comment = "#")
# A tibble: 1 x 3
x y z
1 1 2 3
- 有时,你的数据并没有表头,你可以使用
col_names = FALSE
告诉read_csv()
不要把第一行作为表头,然后用X1
到Xn
依次标注
> read_csv("1,2,3\n4,5,6", col_names = FALSE)
# A tibble: 2 x 3
X1 X2 X3
1 1 2 3
2 4 5 6
此外,你还可以使用 col_names
参数设置列名
read_csv("1,2,3\n4,5,6", col_names = c("x", "y", "z"))
# A tibble: 2 x 3
x y z
1 1 2 3
2 4 5 6
另一个需要调整的选项是 na
,用来标识缺省的值
read_csv("a,b,c\n1,2,.", na = ".")
# A tibble: 1 x 3
a b c
1 1 2 NA
对于 read_tsv()
和 read_fwf()
的读取方式,也是类似的,就不再做详细介绍了。
如果想要进一步了解读取方式,那就要知道 readr
是如何解析每一列,并如何转换为 R
向量的。
与 R 基础操作对比
你可能会问,为什么我不直接用 R
自带的 read.csv
或其他类似的 read.table
等函数来读取文件呢?
其原因是:
首先,通常它的读取速度比
R
基础函数快很多(大约10
倍)。在长时间的运行过程中,会有一个进度条,让你知道程序运行到哪里了。如果你对速度的追求更高,可以尝试data.table::fread()
函数,但是它没有readr
的兼容性好其次,它们产生的是
tibble
格式的数据,不会将字符串转换为factor
,使用行名或列名。最后,它们更容易复制,基础的
R
函数是从你的操作系统和环境变量继承了一些行为,因此在你的计算机上运行的代码可能无法在其他计算机上运行。
思考练习
使用什么函数读取
|
分隔的文件?除了
file
、skip
和comment
之外,read_csv()
和read_tsv()
还有哪些共同的参数?read_fwf()
最重要的参数是什么?-
有时
CSV
文件中的字符串包含,
符号。为了避免这种问题,它们需要被一个引号括起来,比如"
或'
。默认情况下
read_csv()
假设字符被"
包裹,如何读取下面的文本?
"x,y\n1,'a,b'"
- 确定下列每个内联
CSV
文件的错误所在。运行代码时会发生什么?
read_csv("a,b\n1,2,3\n4,5,6")
read_csv("a,b,c\n1,2\n1,2,3,4")
read_csv("a,b\n\"1")
read_csv("a,b\n1,2\na,b")
read_csv("a;b\n1;3")
解析向量
在深入了解 readr
如何从磁盘读取文件之前,我们需要稍微讨论一下 parse_*()
函数
这些函数接受一个字符向量并返回一个更专门的向量,如 logical
, integer
或 date
> str(parse_logical(c("TRUE", "FALSE", "NA")))
logi [1:3] TRUE FALSE NA
> str(parse_integer(c("1", "2", "3")))
int [1:3] 1 2 3
> str(parse_date(c("2010-01-01", "1979-10-14")))
Date[1:2], format: "2010-01-01" "1979-10-14"
这些函数本身很有用,但也是 readr
的一个重要构建部分。
在了解完本节中各个解析器的工作原理后,我们将在下一节中回过头来看看它们是如何组合在一起解析完整的文件
和其他许多 tidyverse
函数一样,parse_*()
函数也是统一的,第一个参数是要解析的字符向量,而 na
参数指定哪些字符串应该被视为缺失值
parse_integer(c("1", "231", ".", "456"), na = ".")
[1] 1 231 NA 456
如果解析失败,你会得到一个警告
> x <- parse_integer(c("123", "345", "abc", "123.45"))
Warning: 2 parsing failures.
row col expected actual
3 -- an integer abc
4 -- no trailing characters 123.45
但是错误并不会包含在输出中
> x
[1] 123 345 NA NA
attr(,"problems")
# A tibble: 2 x 4
row col expected actual
1 3 NA an integer abc
2 4 NA no trailing characters 123.45
如果有许多解析失败,你可以使用 problems()
来获得完整的信息。这会返回一个 tibble
,然后您可以使用 dplyr
对其进行操作。
> problems(x)
# A tibble: 2 x 4
row col expected actual
1 3 NA an integer abc
2 4 NA no trailing characters 123.45
使用解析器主要是为了理解什么是可用的,以及它们是如何处理不同类型的输入。
总共有八个特别重要的解析器
parse_logical()
和parse_integer()
分别解析逻辑和整数值parse_double()
是严格的数字解析器,parse_number()
是灵活的数字解析器。这些并不是你想得那么容易,因为世界上不同地方的数字书写方式不同。parse_character()
解析字符串parse_factor()
创建因子parse_datetime()
,parse_date()
, 和parse_time()
可以解析各种时间和日期格式。
下面将详细介绍,
哦不!明天再说,脖子要断了。
/(ㄒoㄒ)/~~