往期 · 推薦
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note1:緒論
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note2:使用ggplot2進(jìn)行數(shù)據(jù)可視化(上)
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note3:使用ggplot2進(jìn)行數(shù)據(jù)可視化(下)
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note4:使用dplyr進(jìn)行數(shù)據(jù)轉(zhuǎn)換(上)
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note5:使用dplyr進(jìn)行數(shù)據(jù)轉(zhuǎn)換(下)
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note6:使用tibble實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)框
零基礎(chǔ)"機(jī)器學(xué)習(xí)"自學(xué)筆記|Note6:正規(guī)方程及其推導(dǎo)(內(nèi)附詳細(xì)推導(dǎo)過(guò)程)
使用readr進(jìn)行數(shù)據(jù)導(dǎo)入
導(dǎo)入數(shù)據(jù)的方法有很多忆畅,相信大家也已經(jīng)有了自己習(xí)慣的方法揭厚,所以本節(jié)的內(nèi)容只是給大家提供一個(gè)選擇仿粹。所謂技多不壓身僻爽!本節(jié)較多理論性的東西刻两,大家也可以酌情跳過(guò)止潘!當(dāng)然砌烁,如果覺得有幫助的話蔚万,不妨點(diǎn)個(gè)再看或者贊你的支持就是我更新的最大動(dòng)力
7.1 簡(jiǎn)介
本章將學(xué)習(xí)如何將純文本格式的矩形文件讀入 R。雖然本章內(nèi)容只是數(shù)據(jù)導(dǎo)入的冰山一角徽曲,但其中的原則完全適用于其他類型的數(shù)據(jù)零截。本章末尾將提供 一些有用的 R 包,以處理其他類型的數(shù)據(jù)秃臣。
7.2 入門
readr
的多數(shù)函數(shù)用于將平面文件轉(zhuǎn)換為數(shù)據(jù)框涧衙。
? read_csv()
讀取逗號(hào)
分隔文件、read_csv2()
讀取分號(hào)
分隔文件奥此、read_tsv()
讀取制表符
分隔文件弧哎、read_delim()
可以讀取使用任意分隔符
的文件。
? read_fwf()
讀取固定寬度
的文件稚虎。既可以使用 fwf_widths()
函數(shù)按照寬度來(lái)設(shè)定域撤嫩,也可以使用 fwf_positions()
函數(shù)按照位置來(lái)設(shè)定域。read_table()
讀取固定寬度文件的一種常用變體蠢终,其中使用空白字符來(lái)分隔各列非洲。
? read_log()
讀取 Apache 風(fēng)格的日志文件。(但需要檢查是否安裝了 webreadr
包蜕径,(https:// github.com/Ironholds/webreadr)两踏,因?yàn)樵摪挥?read_log()
函數(shù)的開頭,還可以提供很多有用的工具兜喻。)
read_csv()
函數(shù)的第一個(gè)參數(shù)是最重要的梦染,該參數(shù)是要讀取的<u>文件的路徑</u>:
heights <- read_csv("data/heights.csv")`
還可以提供一個(gè)行內(nèi) CSV 文件。
read_csv("a,b,c
1,2,3
4,5,6")
> 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()
函數(shù)都使用數(shù)據(jù)的第一行作為列名稱帕识。
? 有時(shí)文件開頭會(huì)有好幾行元數(shù)據(jù)泛粹。你可以使用 skip = n
來(lái)跳過(guò)前 n 行;或者使用 comment = "#"
來(lái)丟棄所有以 # 開頭的行:
read_csv("The first line of metadata
The second line of metadata
x,y,z
1,2,3", skip = 2)
> read_csv("The first line of metadata
+ The second line of metadata
+ x,y,z
+ 1,2,3", skip = 2)
# A tibble: 1 x 3
x y z
<dbl> <dbl> <dbl>
1 1 2 3
read_csv("# A comment I want to skip
x,y,z
1,2,3", comment = "#")
> read_csv("# A comment I want to skip
+ x,y,z
+ 1,2,3", comment = "#")
# A tibble: 1 x 3
x y z
<dbl> <dbl> <dbl>
1 1 2 3
? 數(shù)據(jù)沒有列名稱肮疗【фⅲ可以使用 col_names = FALSE
來(lái)通知 read_csv()
<u>不要將第一行作為列標(biāo)題</u>,而是將各列依次標(biāo)注為 X1 至 Xn:
read_csv("1,2,3\n4,5,6", col_names = FALSE) #\n 換行
> read_csv("1,2,3\n4,5,6", col_names = FALSE)
# A tibble: 2 x 3
X1 X2 X3
<dbl> <dbl> <dbl>
1 1 2 3
2 4 5 6
或者你也可以向 col_names
傳遞一個(gè)字符向量伪货,以用作列名稱:
read_csv("1,2,3\n4,5,6", col_names = c("x", "y", "z"))
> read_csv("1,2,3\n4,5,6", col_names = c("x", "y", "z"))
# A tibble: 2 x 3
x y z
<dbl> <dbl> <dbl>
1 1 2 3
2 4 5 6
另一個(gè)通常需要修改的選項(xiàng)是 na
们衙。它設(shè)定使用哪個(gè)值(或哪些值)來(lái)表示文件中的缺失值:
read_csv("a,b,c\n1,2,.", na = ".")
> read_csv("a,b,c\n1,2,.", na = ".")
# A tibble: 1 x 3
a b c
<dbl> <dbl> <lgl>
1 1 2 NA
7.2.1 與R基礎(chǔ)包進(jìn)行比較
readr
相較于R基礎(chǔ)包中具有同樣功能的函數(shù),如read.csv()
有以下優(yōu)點(diǎn)
? 一般來(lái)說(shuō)碱呼,比基礎(chǔ)模塊中的函數(shù)速度更快(約快10倍)蒙挑。
? 可以生成 tibble
,并且<u>不會(huì)將字符向量轉(zhuǎn)換為因子</u>愚臀,不<u>使用行名稱忆蚀,也不會(huì)隨意改動(dòng)列名稱</u>。
? 更易于重復(fù)使用姑裂。R 基礎(chǔ)包中的函數(shù)會(huì)繼承操作系統(tǒng)的功能馋袜,并依賴環(huán)境變量,因 此舶斧,可以在你的計(jì)算機(jī)上正常運(yùn)行的代碼在導(dǎo)入他人計(jì)算機(jī)時(shí)桃焕,不一定能正常運(yùn)行。
7.3 解析向量
在詳細(xì)介紹 readr
如何從磁盤讀取文件前捧毛,我們需要先討論一下 parse_*()
函數(shù)族。這些函數(shù)接受一個(gè)字符向量让网,并返回一個(gè)特定向量呀忧,如邏輯、整數(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"
和 tidyverse
中的所有函數(shù)一樣溃睹,parse_*()
函數(shù)族的用法是一致的而账。第一個(gè)參數(shù)是需要解析的字符向量,na
參數(shù)設(shè)定了哪些字符串應(yīng)該當(dāng)作缺失值來(lái)處理:
parse_integer(c("1", "231", ".", "456"), na = ".")
> [1] 1 231 NA 456
如果解析失敗因篇,你會(huì)收到一條警告:
x <- parse_integer(c("123", "345", "abc", "123.45"))
> x <- parse_integer(c("123", "345", "abc", "123.45"))
Warning: 2 parsing failures.
row col expected actual
3 -- an integer abc
4 -- no trailing characters 123.45
#解析失敗的值在輸出中是以缺失值的形式存在的
x
> x
[1] 123 345 NA NA
attr(,"problems")
# A tibble: 2 x 4
row col expected actual
<int> <int> <chr> <chr>
1 3 NA an integer abc
2 4 NA no trailing characters 123.45
在解析函數(shù)的使用方面泞辐,最重要的是要知道有哪些解析函數(shù),以及每種解析函數(shù)用來(lái)處理 哪種類型的輸入竞滓。具體來(lái)說(shuō)咐吼,重要的解析函數(shù)有 8 種。
? parse_logical()
和 parse_integer()
函數(shù)分別解析邏輯值和整數(shù)商佑。
? parse_double()
是嚴(yán)格的數(shù)值型解析函數(shù)锯茄,parse_number()
則是靈活的數(shù)值型解析函數(shù)。
? parse_character()
字符編碼。
? parse_factor()
函數(shù)可以創(chuàng)建因子肌幽,R 使用這種數(shù)據(jù)結(jié)構(gòu)來(lái)表示分類變量晚碾,該變量具有固定數(shù)目的已知值。
? parse_datetime()
喂急、parse_date()
和 parse_time()
函數(shù)可以解析不同類型的日期和時(shí)間格嘁。
7.3.1 數(shù)值
解析數(shù)值似乎是非常直截了當(dāng)?shù)模韵?3 個(gè)問(wèn)題增加了數(shù)值解析的復(fù)雜性廊移。
? 世界各地的人們書寫數(shù)值的方式不盡相同糕簿。例如,有些國(guó)家使用 .
來(lái)分隔實(shí)數(shù)中的整數(shù)和小數(shù)部分画机,而有些國(guó)家則使用 ,
冶伞。
? 數(shù)值周圍經(jīng)常有表示某種意義的其他字符,如 $1000 或 10%步氏。
? 數(shù)值經(jīng)常包含“分組”响禽,以便更易讀,如 1 000 000荚醒,而且世界各地用來(lái)分組的字符也不 盡相同芋类。
為了解決第一個(gè)問(wèn)題,readr
使用了“地區(qū)”這一概念界阁,這是可以按照不同地區(qū)設(shè)置解析選項(xiàng)的一個(gè)對(duì)象侯繁。在解析數(shù)值時(shí),最重要的選項(xiàng)就是用來(lái)表示小數(shù)點(diǎn)的字符泡躯。通過(guò)創(chuàng)建一個(gè)新的地區(qū)對(duì)象并設(shè)定 decimal_mark
參數(shù)贮竟,可以覆蓋 .
的默認(rèn)值:
parse_double("1.23")
> [1] 1.23
parse_double("1,23", locale = locale(decimal_mark = ","))
> [1] 1.23
readr
的默認(rèn)地區(qū)是 US-centric,因?yàn)?R 是以美國(guó)為中心的较剃。
parse_number()
解決了第二個(gè)問(wèn)題:它可以忽略數(shù)值前后的非數(shù)值型字符咕别。這個(gè)函數(shù)特別適合處理貨幣和百分比,也可以提取嵌在文本中的數(shù)值:
parse_number("$100")
> [1] 100
parse_number("20%")
> [1] 20
parse_number("It cost $123.45")
> [1] 123
組合使用 parse_number()
和地區(qū)設(shè)置可以解決最后一個(gè)問(wèn)題写穴,因?yàn)?parse_number()
可以忽略“分組符號(hào)”:
# 適用于美國(guó)
parse_number("$123,456,789")
> [1] 1.23e+08
# 適用于多數(shù)歐洲國(guó)家
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
7.3.2 字符串
R 中惰拱,我們可以使用 charToRaw()
函數(shù)獲得一個(gè)字符串的底層表示:
charToRaw("Hadley")
> [1] 48 61 64 6c 65 79
每個(gè)十六進(jìn)制數(shù)表示信息的一個(gè)字節(jié):48 是 H、61 是 a 等啊送。從十六進(jìn)制數(shù)到字符的這種映射稱為編碼偿短,這個(gè)示例中的編碼方式稱為 ASCII
。ASCII
可以非常好地表示英文字符馋没,因?yàn)樗褪敲绹?guó)信息交換標(biāo)準(zhǔn)代碼(American Standard Code for Information Interchange)的縮寫昔逗。
readr
全面支持 UTF-8
:當(dāng)讀取數(shù)據(jù)時(shí),它假設(shè)數(shù)據(jù)是 UTF-8
編碼的篷朵,并總是使用 UTF-8
編碼寫入數(shù)據(jù)纤子。但對(duì)于從不支持 UTF-8
的那些舊系統(tǒng)中產(chǎn)生的數(shù)據(jù),你的字符串打印出來(lái)就是一堆亂碼。例如:
x1 <- "El Ni\xf1o was particularly bad this year"
x2 <- "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"
要想解決這個(gè)問(wèn)題,需要在 parse_character()
函數(shù)中設(shè)定編碼方式:
parse_character(x1, locale = locale(encoding = "Latin1"))
> [1] "El Ni?o was particularly bad this year"
parse_character(x2, locale = locale(encoding = "Shift-JIS"))
> [1] "こんにちは"
readr
提供了 guess_encoding()
函數(shù)來(lái)幫助你找出編碼方式
guess_encoding(charToRaw(x1))
> encoding confidence
> 1 ISO-8859-1 0.46
> 2 ISO-8859-9 0.23
guess_encoding(charToRaw(x2))
> encoding confidence
> 1 KOI8-R 0.42
guess_encoding()
的第一個(gè)參數(shù)可以是一個(gè)文件路徑控硼,也可以是一個(gè)原始向量(適用于字符串已經(jīng)在R中的情況)泽论。
7.3.3 因子
R 使用因子表示取值范圍是已知集合的分類變量。如果 parse_factor()
函數(shù)的 levels
參數(shù)被賦予一個(gè)已知向量卡乾,那么只要存在向量中沒有的值翼悴,就會(huì)生成一條警告:
fruit <- c("apple", "banana")
parse_factor(c("apple", "banana", "bananana"), levels = fruit)
> 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
7.4 解析文件
現(xiàn)在你已經(jīng)學(xué)會(huì)了如何解析單個(gè)向量,接下來(lái)我們就回到本章的最初目標(biāo)幔妨,研究 readr
是如何解析文件的鹦赎。你將在本節(jié)中學(xué)到以下兩種新技能。
? readr
如何自動(dòng)猜出文件每列的數(shù)據(jù)類型误堡。
? 如何修改默認(rèn)設(shè)置古话。
7.4.1 策略
readr
使用一種啟發(fā)式過(guò)程來(lái)確定每列的類型:先讀取文件的前 1000 行,然后使用(相對(duì)保守的)某種啟發(fā)式算法確定每列的類型锁施∨悴龋可以使用字符向量模擬這個(gè)過(guò)程,先使用 guess_ parser()
函數(shù)返回 readr
最可信的猜測(cè)悉抵,接著 parse_guess()
函數(shù)使用這個(gè)猜測(cè)來(lái)解析列:
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"
str(parse_guess("2010-10-10"))
> Date[1:1], format: "2010-10-10"
7.4.2 問(wèn)題
這個(gè)部分內(nèi)容都是原理肩狂,對(duì)實(shí)際使用沒有太大影響,我這里就跳過(guò)了姥饰。
7.5 寫入文件
readr
還提供了兩個(gè)非常有用的函數(shù)傻谁,用于將數(shù)據(jù)寫回到磁盤:write_csv()
和 write_ tsv()
。這兩個(gè)函數(shù)輸出的文件能夠順利讀取的概率更高列粪,因?yàn)椋?/p>
? 它們總是使用 UTF-8
對(duì)字符串進(jìn)行編碼审磁;
? 它們使用 ISO 8601
格式來(lái)<u>保存日期和日期時(shí)間數(shù)據(jù)</u>,以便這些數(shù)據(jù)不論在何種環(huán)境下 都更容易解析岂座。 如果想要將 <u>CSV 文件導(dǎo)為 Excel 文件</u>态蒂,可以使用 write_excel_csv()
函數(shù),該函數(shù)會(huì)在文件開頭寫入一個(gè)特殊字符(字節(jié)順序標(biāo)記)掺逼,告訴 Excel 這個(gè)文件使用的是 UTF-8
編碼。 這幾個(gè)函數(shù)中最重要的參數(shù)是 x
(要保存的數(shù)據(jù)框)和 path
(保存文件的位置)瓤介。還可以使 用 na
參數(shù)設(shè)定如何寫入缺失值吕喘,如果想要追加到現(xiàn)有的文件,需要設(shè)置 append
參數(shù):
write_csv(challenge, "challenge.csv")
注意刑桑,當(dāng)保存為 CSV 文件時(shí)氯质,類型信息就丟失了。
這使得 CSV 文件在暫存臨時(shí)結(jié)果時(shí)有些不可靠——每次加載時(shí)都要重建列類型祠斧。以下是兩種替代方式闻察。
? write_rds()
和 read_rds()
函數(shù)是對(duì)基礎(chǔ)函數(shù) readRDS()
和 saveRDS()
的統(tǒng)一包裝。前者可以將數(shù)據(jù)保存為 R 自定義的二進(jìn)制格式,稱為 RDS 格式:
write_rds(challenge, "challenge.rds")
read_rds("challenge.rds")
> write_rds(challenge, "challenge.rds")
> read_rds("challenge.rds")
# A tibble: 2,000 x 2
x y
<dbl> <lgl>
1 404 NA
2 4172 NA
3 3004 NA
4 787 NA
5 37 NA
6 2332 NA
7 2489 NA
8 1449 NA
9 3665 NA
10 3863 NA
# ... with 1,990 more rows
? feather包
實(shí)現(xiàn)了一種快速二進(jìn)制格式辕漂,可以在多個(gè)編程語(yǔ)言間共享:
install.packages("feather")
library(feather)
write_feather(challenge, "challenge.feather")
read_feather("challenge.feather")
> read_feather("challenge.feather")
# A tibble: 2,000 x 2
x y
<dbl> <lgl>
1 404 NA
2 4172 NA
3 3004 NA
4 787 NA
5 37 NA
6 2332 NA
7 2489 NA
8 1449 NA
9 3665 NA
10 3863 NA
# ... with 1,990 more rows
feather
要比 RDS
速度更快呢灶,而且可以在 R 之外使用。RDS
支持列表列,feather
目前還不行钉嘹。
8.6 其他類型的數(shù)據(jù)
要想將其他類型的數(shù)據(jù)導(dǎo)入 R 中鸯乃,可以從下列的 tidyverse
包開始。
對(duì)矩形數(shù)據(jù)來(lái)說(shuō):
? haven
可以讀取 SPSS跋涣、Stata 和 SAS 文件缨睡;
? readxl
可以讀取 Excel 文件(.xls 和 .xlsx 均可);
? 配合專用的數(shù)據(jù)庫(kù)后端程序(如 RMySQL陈辱、RSQLite奖年、RPostgreSQL 等),DBI
可以對(duì)相 應(yīng)數(shù)據(jù)庫(kù)進(jìn)行 SQL 查詢沛贪,并返回一個(gè)數(shù)據(jù)框陋守。
對(duì)于層次數(shù)據(jù),可以使用 jsonlite
讀取 JSON 串鹏浅,使用 xml2
讀取 XML 文件嗅义。對(duì)于其他的文件類型,可以學(xué)習(xí)一下 R 數(shù)據(jù)導(dǎo)入 / 導(dǎo)出手冊(cè)([https://cran.r-project.org/doc/ manuals/r-release/R-data.html](https://cran.r-project.org/doc/ manuals/r-release/R-data.html))隐砸。