36.关于readr如何解析文件
【上一篇:35.关于prse系列函数之解析日期和时间】
【下一篇:37.关于readr如何写入文件】
前面说过readr包中的read_*()系列函数读取文件后返回的是一个tibble,带有每列的列类型信息。那函数是怎么判断每列的类型的呢?
readr包在解析文件的时候,会根据文件的前1000行判断每列的数据类型。guess_parse()函数用来猜测向量的类型,然后parse_guess()函数根据猜测出的结果来解析整列。两者的Usage为:
guess_parser(
x,
locale = default_locale(),
guess_integer = FALSE,
na = c("", "NA")
)
x:向量或者字符串
locale:控制默认时区、编码、小数点、大标记和日/月名称。
guess_integer:如果为TRUE,猜测整数类型,如果为FALSE,猜测所有数字类型。
na:需要解析为缺失值的向量,如果na=character()表示没有缺失值。
------------------------------------------------------------------
> guess_parser("2010-10-01")
[1] "date"
> guess_parser("15:01")
[1] "time"
> guess_parser(c("TRUE", "FALSE"))
[1] "logical"
> guess_parser(c("1", "5", "9"))
[1] "double"
> guess_parser(c("12,352,561"))
[1] "number"
------------------------------------------------------------------
parse_guess(
x,
na = c("", "NA"),
locale = default_locale(),
trim_ws = TRUE,
guess_integer = FALSE
)
> str(parse_guess("2010-10-10"))
Date[1:1], format: "2010-10-10"
函数尝试下列每种类型,当找到匹配时停止:
logical:仅包含 “F”, “T”, “FALSE”, 或 “TRUE”。
integer:仅包含数字字符和“-”。
double:仅包含有效的双精度 (包括类似4.5e-5
)
number:包含内有分组标记的有效双精度浮点数。
time:匹配默认的 time_format
。
date:匹配默认的 date_format
。
date-time: 任何 ISO8601 date。
如果上述类型都不满足,将返回一个字符串向量。
但是,猜毕竟是猜,而且只是用前1000行猜,当然会猜错。比如,根据前1000行猜的是logical,但实际整列是date,只是不凑巧前1000行的值缺失才导致猜错了,所以在进一步解析整列的时候,碰到真正的date行就会报错(默认打印前5个报错),如下:
challenge <- read_csv(readr_example("challenge.csv"))
# 同时可以用problems(challenge)查看更确切的报错信息。
> problems(challenge)
# A tibble: 1,000 x 5
row col expected actual file
<int> <chr> <chr> <chr> <chr>
1 1001 y 1/0/T/F/TRUE/~ 2015-01-~ 'D:/Program Files/R-4.1.0/library/rea~
2 1002 y 1/0/T/F/TRUE/~ 2018-05-~ 'D:/Program Files/R-4.1.0/library/rea~
3 1003 y 1/0/T/F/TRUE/~ 2015-09-~ 'D:/Program Files/R-4.1.0/library/rea~
4 1004 y 1/0/T/F/TRUE/~ 2012-11-~ 'D:/Program Files/R-4.1.0/library/rea~
5 1005 y 1/0/T/F/TRUE/~ 2020-01-~ 'D:/Program Files/R-4.1.0/library/rea~
6 1006 y 1/0/T/F/TRUE/~ 2016-04-~ 'D:/Program Files/R-4.1.0/library/rea~
7 1007 y 1/0/T/F/TRUE/~ 2011-05-~ 'D:/Program Files/R-4.1.0/library/rea~
8 1008 y 1/0/T/F/TRUE/~ 2020-07-~ 'D:/Program Files/R-4.1.0/library/rea~
9 1009 y 1/0/T/F/TRUE/~ 2011-04-~ 'D:/Program Files/R-4.1.0/library/rea~
10 1010 y 1/0/T/F/TRUE/~ 2010-05-~ 'D:/Program Files/R-4.1.0/library/rea~
# ... with 990 more rows
还有一个函数叫做stop_for_problems(),正常情况下即使某些列解析不正确也只是
打印个警告,不影响返回一个tibble(虽然里面某些值是错的)。
用stop_for_problems()可以在遇到解析错误时停止解析,这很有用。
> stop_for_problems(challenge)
Error: 1000 parsing failures
![](https://img.haomeiwen.com/i17752145/dbd2784629c316fa.png)
如何解决这些问题呢?也就是如何才能正确解析文件呢?还记得前面将read_*()系列函数的时候吗?这些函数都有一个参数col_types,这个参数就是用来指定按照什么类型解析某列的,例如:
# 直接指定按照date来解析y列就可以解决解析错误的问题了
challenge <- read_csv(
readr_example("challenge.csv"),
col_types = cols(
x = col_double(),
y = col_date()
)
)
其实也可以设置guess_max参数,默认是1000,你可以设置你想要的。
还可以将所有的列都认为是character进行解析
challenge2 <- read_csv(readr_example("challenge.csv"),
col_types = cols(.default = col_character())
)
本篇总结:
1)read_*()系列函数默认是通过前1000行来判断每列的类型的
2)会判断错,这时候就用上了read_*()系列函数的col_types参数
3)了解这一切的目的都是为了能正确解析文件中的信息。函数自己猜不对,你就告诉函数每列是啥类型,函数就会乖乖按照你的指示返回你想要的正确的tibble了。