
Hadley Wickham 和 RStudio 團隊開發(fā)了一個新的用于文本數(shù)據(jù)讀取的包,那就是readr包。readr包提供了幾個新的函數(shù),能夠更快的讀取文本文件.
#1. 相比于R基礎包
- 比基礎模塊中函數(shù)速度更快(約快10倍);
- 生成tibble,并且不會把字符向量轉換成因子,不使用行名稱,也不會隨意改動列名稱;
- 更易于重復使用;
#2. readr介紹
##2.1 readr()也是tidyverse的核心包之一。
- readr 的多數(shù)函數(shù)用于將平面文件轉換為數(shù)據(jù)框。
read_csv()讀取逗號分隔文件
read_csv2()讀取分號分隔文件
read_tsv()讀取制表符分隔文件
read_delim()讀取使用任意分隔符的文件
read_fwf()讀取固定寬度文件;既可以使用fwf_widths()函數(shù)按照寬度來設定域,也可以使用fwf_positions()函數(shù)按照位置來設定域。read_table()讀取固定寬度文件的一種常用變體,其中使用空白字符來分隔各列
read_log()讀取Apache風格的日志文件。
read_csv()函數(shù)使用數(shù)據(jù)的第一行作為列名稱
read_table 可用于替代read.table();但是read.table()支持文件列之間存在不等長空格,read_table()要求列必需對齊;
有時候文件有幾行元數(shù)據(jù),可以使用skip=n來跳過前n行;或者使用comment="#"來丟棄所有以#開頭的行;
##2.2 與R基礎包進行比較
- 比基礎模塊中函數(shù)速度更快(約快10倍)
- 生成tibble,并且不會把字符向量轉換成因子,不使用行名稱,也不會隨意改動列名稱
- 更易于重復使用
#3. 解析向量
parse_*()函數(shù)族接受一個字符向量,并返回一個特定向量,如邏輯、整數(shù)或日期向量
> 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"
##3.1 數(shù)值解析
- parse_integer() 解析整數(shù);
- parse_double()和parse_number()都是數(shù)值型解析函數(shù);
對于數(shù)值型解析主要會遇到3個問題:
1. 各地數(shù)值書寫方式不同,小數(shù)分隔號有`.`和`,`
2. 數(shù)值賦予某種實際意義時,可能會加上某種符號,如$100或10%
3. 數(shù)值的分組處理,如1 000 000
對于第一個問題,可以通過創(chuàng)建一個新的地區(qū)對象設定參數(shù)decimal_mark解決;readr()默認的地區(qū)時美國。
parse_double("1.23")
parse_double("1,23",locale = locale(decimal_mark = ","))
- parse_number()可以忽略數(shù)值前后的非數(shù)值型字符;
> parse_number("$100")
[1] 100
> parse_number("20%")
[1] 20
> parse_number("It cost $123.45")
[1] 123.45
- parse_number()結合地區(qū)設置可以解決第三個問題;
> parse_number("$123,456,789")
[1] 123456789
#適用于歐洲多數(shù)國家
> parse_number("$123.456.789",locale = locale(grouping_mark = "."))
[1] 123456789
#適用于瑞士
> parse_number("$123'456,789",locale = locale(grouping_mark = "'"))
[1] 123456
##3.2 字符串解析
-
parse_character()函數(shù)用于字符串解析
字符串解析時需要注意編碼形式,默認編碼方式時UTF-8;
> x2<-"\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"
> parse_character(x2,locale = locale(encoding = "shift-JIS"))
[1] "こんにちは"
? 對于不知道編碼方式的字符串,可以使用guess_encoding(charToRaw())找出編碼方式,charToRaw()可以返回字符串的底層表示;
> guess_encoding(charToRaw(x2))
# A tibble: 1 x 2
encoding confidence
<chr> <dbl>
1 KOI8-R 0.42
##3.3 因子解析
- parse_factor()函數(shù)用于解析因子,其中國levels參數(shù)設置水平。
> fruit<-c("apple","banana")
> parse_factor(c("apple","banana","bananana"),levels = fruit)
Warning: 1 parsing failure.
row col expected actual
3 -- value in level set bananana
[1] apple banana <NA>
attr(,"problems")
# A tibble: 1 x 4
row col expected actual
<int> <int> <chr> <chr>
1 3 NA value in level set bananana
Levels: apple banana
##3.4 日期、日期時間和時間解析
- parse_datetime() 接受符合ISO 8601標準的日期時間,其中日期的各個部分按從大到小的順序排列,即年、月、日,小時,分鐘、秒;
> parse_datetime("2010-10-01T2010")
[1] "2010-10-01 20:10:00 UTC"
- parse_date() 接受年月日;
> parse_date("2010-10-01")
[1] "2010-10-01"
- parse_time() 接受小時;但是還可以加上分鐘,秒,以及a.m./p.m.標識符
> parse_time("01:01 am")
01:01:00
- R 基礎包中沒有能夠很好表示時間數(shù)據(jù)的內置類,但是可以使用hms包提供的時間類。
> library(hms)
> parse_date("01/02/15","%m/%d/%y")
[1] "2015-01-02"
#4. 解析文件
##4.1 每列數(shù)據(jù)類型確定
? 解析文件,首要任務就是對文件每列數(shù)據(jù)類型的確定;大多數(shù)工具會根據(jù)文件header或隨機抽取一定數(shù)量行數(shù)確定數(shù)據(jù)類型;readr 通過讀取文件前1000行來確定每列的類型,使用guess_parser()函數(shù)返回readr解析的數(shù)據(jù)類型,parse_guess()利用這個類型去解析文件的數(shù)據(jù)。
> guess_parser("2010-10-01")
[1] "date"
> guess_parser("15:01")
[1] "time"
? 遇到特殊情況,讀取1000行的方法是行不通的;這時可以調控一些參數(shù)來解決遇到的問題。
col_types: 在文件讀取時,通過參數(shù)col_types指定每列的類型;
> challenge<-read_csv(readr_example("challenge.csv"))
Parsed with column specification:
cols(
x = col_double(),
y = col_logical()
)
Warning: 1000 parsing failures.
row col expected actual file
1001 y 1/0/T/F/TRUE/FALSE 2015-01-16 'C:/Users/labworker/Documents/R/win-library/3.5/readr/extdata/challenge.csv'
1002 y 1/0/T/F/TRUE/FALSE 2018-05-18 'C:/Users/labworker/Documents/R/win-library/3.5/readr/extdata/challenge.csv'
1003 y 1/0/T/F/TRUE/FALSE 2015-09-05 'C:/Users/labworker/Documents/R/win-library/3.5/readr/extdata/challenge.csv'
1004 y 1/0/T/F/TRUE/FALSE 2012-11-28 'C:/Users/labworker/Documents/R/win-library/3.5/readr/extdata/challenge.csv'
1005 y 1/0/T/F/TRUE/FALSE 2020-01-13 'C:/Users/labworker/Documents/R/win-library/3.5/readr/extdata/challenge.csv'
.... ... .................. .......... ............................................................................
See problems(...) for more details.
> head(challenge)
# A tibble: 6 x 2
x y
<dbl> <lgl>
1 404 NA
2 4172 NA
3 3004 NA
4 787 NA
5 37 NA
6 2332 NA
> challenge<-read_csv(readr_example("challenge.csv"),
col_types = cols(
x = col_double(),
y = col_character()
)
)
guess_max: 指定用于解析列變量類型的行數(shù);
n_max():指定文件讀入行數(shù);在處理大內存文件時相當有用;
read_lines(): 按行讀入文件
#5. 寫入文件
- write.csv(), write.tsv() 常用于將數(shù)據(jù)輸出到磁盤,默認使用UTF-8編碼;
write_csv(challenge,"challenge.csv")
read_csv("challenge.csv")
? 但是這種輸出方式的缺點就是無法保留列類型信息,當再次讀入文件時需要重新判定類的類型;這對于數(shù)據(jù)處理過程中輸出讀取臨時文件會產(chǎn)生沒必要的麻煩或錯誤;如果要避免這樣的現(xiàn)象,可以使用其它輸出方法:write_rds()和write_feather(), 后者需要調用feather包。
- write_rds()聯(lián)合read_rds()使用,write_rds()將數(shù)據(jù)保存為自定義的二進制形式(RDS格式)
write_rds(challenge,"challenge.csv")
read_rds("challenge.csv")
- feather包也是實現(xiàn)一種二進制形式,可以在多個編程語言之間共享;相比于RDS,速度更快。
library(feather)
write_feather(challenge,"challenge.csv")
read_feather("challenge.csv")
參考
New packages for reading data into R — fast
R 數(shù)據(jù)科學