第八章-使用readr进行数据的导入
readr读取数据
parse_*函数簇——解析数据(单个向量)
——解析文件
提要:
1.readr函数中掌握read.csv逗号分隔,read.delim任意分隔
2.readr函数中一些参数
- skip = n 跳过
- comment = “#” 忽略#开头
- col_names = FALSE 第一行不是列名
- col_names=c(“x”,“y”,“z”) 重新设置列名
- na="." 点最为na读取
- readr example()函数的用法,它可以找到包含在R包中的文件的路径。
3.读取数据之前,要对数据解析,一种数据有多中表达形式
(1) 数值 parse_number忽略字符串中任何其他非数字符号
decimal_mark = ","
grouping_mark="."忽略分组符号
(2)字符串
1.准备工作
library(tidyverse)
使用readr包将平面文件加载到R中
函数 | 描述 |
read_csv() | 读取逗号分隔文件 |
read_csv2() | 读取分号分隔文件 |
read_tsv() | 读取制表符分隔文件 |
read_delim() | 可以读取使用任意分隔符的文件 |
read_fuf() | 读取固定宽度的文件。read_table()是他的变体。 |
read_log() | 读取Apache风格的日志文件。 |
read_lines() | 按行读入字符向量 |
read_file() | 读入一个长度为1的字符向量 |
注意:
- 使用readr中函数来读取数据,比R基础包中的读取函数效率更高
例如readr中函数比R基础模块函数read.csv()速度约快10倍
data.table::fread()读取比readr更快 - readr中函数可以生成tibble,并且不会将字符向量转换为因子,不使用行名称,也不会随意改动列名称。
- readr中函数易于重复使用
2.read_csv()的参数
- 可以使用skip = n 来跳过前n 行;
- 用comment = “#” 来丢弃所有以 # 开头的行
- 默认第一行为列名,取消默认用col_names = FALSE,定义列名向col_names传递一个字符向量,用做列名称
- 将某些值读取为缺失值,na="."
- "\n"是非常便捷的快捷方式,用于添加新行
例子:
read_csv("The first line of metadata
The second line of metadata
x,y,z
1,2,3", skip = 2)
read_csv("a,b,c
1,2,3
4,5,6")
# A tibble: 2 x 3
# a b c
# <dbl> <dbl> <dbl>
# 1 1 2 3
# 2 4 5 6
read_csv("a,b,c\n1,2,3\n4,5,6")
read_csv("1,2,3\n4,5,6",col_names=c("x","y","z"))
练习
(1) 如果一个文件中的域是由“|”分隔的,那么应该使用哪个函数来读取这个文件?
read_delim(file, delim = "|")
(2) 除了file、skip 和comment,还有哪些参数是read_csv() 和read_tsv() 这两个函数共有的?
union(names(formals(read_csv)), names(formals(read_tsv)))
(3) read_fwf() 函数中最重要的参数是什么?
read_fwf()读取“固定宽度格式” 的最重要的参数是col_positions告诉函数数据列开始和结束的位置。
(4) 有时CSV 文件中的字符串会包含逗号。为了防止引发问题,需要用引号(如" 或’)将逗号围起来。按照惯例,read_csv() 默认引号为",如果想要改变默认值,就要转而使用read_delim() 函数。要想将以下文本读入一个数据框,需要设定哪些参数?
"x,y\n1,'a,b'"
x <- "x,y\n1,'a,b'"
read_csv(x, quote = "'")
3.解析向量
parse_*() 函数接受一个字符型向量,并返回一个特定向量,如逻辑、整数或日期,改变了数据类型。
第一个参数是需要解析的字符向量,na参数设定了哪些字符串应该当作缺失值来处理:
parse_integer(c("1","231",".","456"),na=".")
#>[1]1231NA456
parse_logical()#解析逻辑值
parse_integer()#解析整数
parse_double()#严格的数值型
parse_number()#灵活的数值型
parse_character()
parse_factor()
parse_datetime()#日期型和SQL一样
parse_date()
parse_time()
输入字符串,返回定义的类型
parse_logical(c("TRUE","FALSE","NA"))
[1] TRUE FALSE NA
str(parse_logical(c("TRUE","FALSE","NA")))
>logi [1:3] TRUE FALSE NA
str(parse_integer(c("1","2","3")))
#>int [1:37123
str(parse_date(c("2010-01-01","1979-10-14")))
#>Date[1:2],format:"2010-01-01""1979-10-14"
解析失败可用problems(x)获取失败信息集合,可用dplyr处理缺失值。
3.1.数值
生活中同一个数值有多个表达形式
readr使用“地区”这个概念,可以按照不同地区设置解析选项的一个对象
默认小数点是"."有的国家用逗号作为小数点,需要用参数
locale = locale(decimal_mark = “,”)设置。
parse_double("1.23")
#> [1] 1.23
parse_double("1,23", locale = locale(decimal_mark = ","))
#> [1] 1.23
数字前后有货币、百分比、无关文本等等,可用parse_number提取,也可以提取嵌在文本中的数值
parse_number()解决了第二个问题:它可以忽略数值前后的非数值型字符。
parse_number("$100")
#>[1]100
parse_number("20%")
#>[1]20
parse_number("It cost $123.45")
#>[17123
组合使用parse_number()和地区设置可以解决最后一个问题,
因为parse_number()可以忽略“分组符号”:
适用于美国
parse_number("$123,456,789")#默认
#>[1]1.23e+08
适用于多数欧洲国家
parse_number(
"123.456.789",locale=locale(grouping_mark="."))#忽略“分组符号”
#>[1]1.23e+08
适用于瑞士
parse_number(
"123'456'789",locale=locale(grouping_mark="'"))#忽略“分组符号”
#>[1]1.23e+08
3.2字符串
生活中同一个字符串有多个表达形式
parse_character()
用charToRaw()获得一个字符串的底层编码。
charToRaw("Hadley")
#>[1]48 61 64 6c 65 7
ASCII可以非常好地表示英文字符9
readr全面支持UTF-8:当读取数据时,它假设数据是UTF-8编码的,并总是使用UTF-8编码写入数据
处理数据文本乱码,可以用
locale = locale(encoding = "")
猜测编码方式:guess_encoding(charToRaw())
x1="\xceҰ�\xc4\xe3"
parse_character(x1,locale=locale(encoding="chr"))
guess_encoding(charToRaw(x1))
3.3因子
R使用因子表示取值范围是已知集合的分类变量。
如果parse_factor函数的levels参数被赋予一个已知向量,
那么只要存在向量中没有的值,就会生成一条警告:
fruit <- c(“apple”, “banana”,“bananana”)
parse_factor(c(“apple”, “banana”, “bananana”), levels = fruit)
#[1] apple banana bananana
#Levels: apple banana bananana
3.4日期
注意:通常是这样
parse_date("01/02/15","%m/%d/%y")
#>[1]"2015-01-02"
parse_date("01/02/15","%d/%m/%y")
#>[1]"2015-02-01"
parse_date("01/02/15","%y/%m/%d")
#>[1]"2001-02-15"
1.日期时间型
parse_datetime期待的是符合ISO8601标准的日期时间。
ISO8601是一种国际标准,其中日期的各个部分按从大到小的顺序排列,即年、月、日、小时、分钟、秒:
parse_datetime("2010-10-01T2010")
#>[1]"2010-10-0120:10:00 UTC"
如果时间被省略了,那么它就会被设置为午夜
parse_datetime("20101010")
#>[1]"2010-10-10 UTC"
2.日期型
parse_date期待的是四位数的年份、一个-或/、月、一个-或/,然后是日:
parse_date("2010-10-01")
#>[1]"2010-10-01"
3.时间型
parse_time期待的是小时、:、分钟、可选的:和秒,以及一个可选的a.m./p.m.标识符:
library(hms)
parse_time("01:10 am")
#>01:10:00
parse_time("20:10:01")
#>20:10:01
4.解析文件
先是用guess_parser() 猜测数据类型
parse_guess() 解析列,列是向量。
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]"integer"
guess_parser(c("12,352,561"))
#>[1]"number"
readr首先读取1000行,然后开始启发式猜测,猜测文件中的数据进行自动解析
可以猜测:逻辑值、整数、双精度浮点数、数值、时间、日期、日期时间等
如果都不匹配,就默认为这一列为字符串
但是按照上面这样,会出现一些问题
readr中包含了一份非常有挑战性的CSV文件,该文件可以说明以上两个问题。
readr example()函数的用法,它可以找到包含在R包中的文件的路径。
challenge <- read_csv(readr_example(“challenge.csv”))
自动根据前1000行,猜测x列为整数,y列为数值。
在1000列之后都是failure了,因为有拖尾字符。
实际上1000行后x列为双精度浮点数,y列为日期
。因此我们在读取命令中加入col_types,指定x列为col_double(),
y列为col_date()
可以更改列的类型
challenge<-read_csv(
readr_example("challenge. csv"),
coL_types=cols(
x=coL_integer(),
y=col_character()
))
接着修改x列的类型:
challenge<-read_csv(
readr_example("challenge. csv"),
coL_types=cols(
x=coL_double(),
y=col_character()
))
接着修改y列的类型:
challenge<-read_csv(
readr_example("challenge. csv"),
coL_types=cols(x=col_double(), y=coL_date()))
还可以更改一次读取的最大值
challenge2<-read_csv(
readr_example("challenge. csv"), guess_max=1001)
另外将所有列作为字符向量读入:
challenge2 <- read_csv(readr_example("challenge.csv"),
col_types = cols(.default = col_character())
)
使用type_convert()转换数据类型:
df <- tribble(
~x, ~y,
"1", "1.21",
"2", "2.32",
"3", "4.56"
)
df
#> # A tibble: 3 × 2
#> x y
#> <chr> <chr>
#> 1 1 1.21
#> 2 2 2.32
#> 3 3 4.56
# 注意列类型
type_convert(df)
#> Parsed with column specification:
#> cols(
#> x = col_integer(),
#> y = col_double()
#> )
#> # A tibble: 3 × 2
#> x y
#> <int> <dbl>
#> 1 1 1.21
#> 2 2 2.32
#> 3 3 4.56
5.保存、导出
readr还提供了两个非常有用的函数,用于将数据写回到磁盘:
write_csv()
write_tsv()
如果想要将CSV文件导为Excel文件,可以使用write_excel_csv()函数
write_csv导出后,列的数据类型会丢失。
替代方式:
(1)write_rds(),read_rds-R自定义的二进制格式RDS格式
write_rds(challenge,"challenge.rds")
read_rds("challenge.rds")
(2)feather包中的write_feather和read_feather-在多种编程语言间通用。
library(feather)
write_feather(challenge,"challenge.feather")
read_feather("challenge.feather")
feather要比RDS速度更快,而且可以在R之外使用。
6.其他类型的数据
• haven 可以读取SPSS、Stata 和SAS 文件;
• readxl 可以读取Excel 文件(.xls 和.xlsx 均可);
library(readxl)
d <- read_excel(“d.xlsx”)
View(d)
• 配合专用的数据库后端程序(如RMySQL、RSQLite、RPostgreSQL等),
DBI可以对相应数据库进行SQL查询,并返回一个数据框。