1.4 readr

readr提供了一种快速友好的方式读取矩形数据3(如:csv,tsv,fwf),且当读取大型数据集时默认有进度条显示。

如果对readr包不熟悉,可以直接阅读包作者,大神Hadley Wickham的书R for data science 中data import chapter章节。

1.4.1 安装

由于readr包是tidyverse系列核心包,可以直接安装tidyverse使用,或者单独安装readr。

# 安装整个tidyverse
install.packages("tidyverse")

# 仅安装readr
install.packages("readr")

# 从github安装开发版
# install.packages("devtools")
devtools::install_github("tidyverse/readr")

1.4.2 用法

readr包是tidyverse系列的核心包,可以加载tidyverse使用。

library(tidyverse)
# 或者
library(readr)

1.4.2.1 主要函数

readr包支持七种read_功能的文件格式。

read_csv():逗号分隔符文件 - read_tsv():制表符分割文件 - read_delim():规定分隔符文件 - read_fwf():固定宽度文件 - read_table():表格文件,列间用空格隔开 - read_log():Web日志文件

在大多数情况下,我们常使用read_csv(),提供文件路径,将得到数据表。示例如下:

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()
#> )

通过上述输出反馈,我们可以知道读进去的数据集每列类型。如果发现不对可以通过col_types参数修改。大多数情况下,我们并不需要指定列的类型,readr会自动猜测列类型。

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()
  )
)

1.4.2.2 参数

read_csv()的参数如下:

read_csv(
  file,
  col_names = TRUE,
  col_types = NULL,
  locale = default_locale(),
  na = c("", "NA"),
  quoted_na = TRUE,
  quote = "\"",
  comment = "",
  trim_ws = TRUE,
  skip = 0,
  n_max = Inf,
  guess_max = min(1000, n_max),
  progress = show_progress(),
  skip_empty_rows = TRUE
)

通过对 readxl 包的了解,我们发现两个包的读写函数的部分参数是一致的。

col_types :指定列类型,可用项如下所示(含简写): c = character,i = integer,n = number,d = double,l = logical,f = factor,D = date,T = date time,t = time,默认值为 guess。

locale:locale参数是 readr 包中很重要的一个参数,指定日期使用的月和日的名称,时区,字符编码,日期格式,数字的小数和点位数和分隔符。

locale()的第一个参数是date_names,控制月份和日期的名称,指定最简单的方式ISO 639 language code

locale('zh') # 中文
#> <locale>
#> Numbers:  123,456.78
#> Formats:  %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days:   星期日 (周日), 星期一 (周一), 星期二 (周二), 星期三 (周三), 星期四
#>         (周四), 星期五 (周五), 星期六 (周六)
#> Months: 一月 (1月), 二月 (2月), 三月 (3月), 四月 (4月), 五月 (5月), 六月 (6月),
#>         七月 (7月), 八月 (8月), 九月 (9月), 十月 (10月), 十一月 (11月),
#>         十二月 (12月)
#> AM/PM:  上午/下午
locale('ja') #日本
#> <locale>
#> Numbers:  123,456.78
#> Formats:  %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days:   日曜日 (日), 月曜日 (月), 火曜日 (火), 水曜日 (水), 木曜日 (木), 金曜日
#>         (金), 土曜日 (土)
#> Months: 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月
#> AM/PM:  午前/午後
locale('ko') #韩国
#> <locale>
#> Numbers:  123,456.78
#> Formats:  %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days:   <U+C77C><U+C694><U+C77C> (<U+C77C>), <U+C6D4><U+C694><U+C77C> (<U+C6D4>), <U+D654><U+C694><U+C77C> (<U+D654>), <U+C218><U+C694><U+C77C> (<U+C218>), <U+BAA9><U+C694><U+C77C> (<U+BAA9>), <U+AE08><U+C694><U+C77C>
#>         (<U+AE08>), <U+D1A0><U+C694><U+C77C> (<U+D1A0>)
#> Months: 1<U+C6D4>, 2<U+C6D4>, 3<U+C6D4>, 4<U+C6D4>, 5<U+C6D4>, 6<U+C6D4>, 7<U+C6D4>, 8<U+C6D4>, 9<U+C6D4>, 10<U+C6D4>, 11<U+C6D4>, 12<U+C6D4>
#> AM/PM:  <U+C624><U+C804>/<U+C624><U+D6C4>

编码和时区问题是我们常面临的问题, 不正确设定导致我们的数据读取错误。

read_csv(readr_example("mtcars.csv"),locale = locale(encoding = 'UTF-8',tz = 'Asia/Shanghai'))

关于locales,详细信息查看手册vignette("locales")

1.4.3 导出功能

由于系统缘故,在win系统下可能面临编码问题。我用readr导出数据时一般采用write_excel_csv()功能导出,目前还未遇到乱码情况。

需要说明的是write_系列函数可以将输出文件压缩。

data(storms, package = "dplyr")
write_csv(storms, "storms.csv")
write_csv(storms, "storms.csv.gz")

1.4.4 总结

大部分情况下,当数据整洁时且不涉及时间(日期不影响)时,采用默认参数读取数据即可。当数据集前面行缺失值较多,readr自动猜数据列类型错误时,需要我们人为指定列类型。

read_csv('test.csv',col_types = 'cccnnnnDcnn')

由于 Excel 数字位数限制,在输出数字订单号或身份证时需要注意,:

id_card <- c('440327199910010123','440327199910010125')
write_excel_csv(data.frame(id_card),'test.csv')

Excel 最多只能存储15位数字型数字,15为之后都为0。

上面的输出显然会改变真实的身份证号码,这时我们就建议输出为xlsx的字符型或者是txt等格式,因为输出CSV会导致后面的全部变成0。

当编码时区不一致时,需指定locale(),如下:

read_csv(readr_example("mtcars.csv"),locale = locale(encoding = 'UTF-8',tz = 'Asia/Shanghai'))

  1. 矩形数据英文中表示为 rectangular data,矩形数据每一列都是变量(特征),而每一行都是案例或记录,关系数据库中的单表就是矩形数据的一种。↩︎