36.关于readr如何解析文件

2021-08-21  本文已影响0人  心惊梦醒

【上一篇: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
报错日志
    如何解决这些问题呢?也就是如何才能正确解析文件呢?还记得前面将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了。

【上一篇:35.关于prse系列函数之解析日期和时间】
【下一篇:37.关于readr如何写入文件】

上一篇 下一篇

猜你喜欢

热点阅读