R數(shù)據(jù)科學(xué)chapter8

library(tidyverse)

#使用readr進行數(shù)據(jù)導(dǎo)入

#? read_csv() 讀取逗號分隔文件、

#read_csv2() 讀取分號分隔文件(這在用 , 表示小數(shù)位的國家非常普遍)、

#read_tsv() 讀取制表符分隔文件、

#read_delim() 可以讀取使用任意分隔符的文件。

#? read_fwf() 讀取固定寬度的文件。

#既可以使用 fwf_widths() 函數(shù)按照寬度來設(shè)定域,也可以使用fwf_positions() 函數(shù)按照位置來設(shè)定域。

#read_table() 讀取固定寬度文件的一種常用變體,其中使用空白字符來分隔各列。

#? read_log() 讀取 Apache 風(fēng)格的日志文件。(但需要檢查是否安裝了 webreadr 包,https:// github.com/Ironholds/webreadr,因為該包位于 read_log() 函數(shù)的開頭,還可以提供很多 有用的工具。)

#read_csv() 函數(shù)的第一個參數(shù)是最重要的,該參數(shù)是要讀取的文件的路徑

#當(dāng)運行read_csv() 時,它會打印一份數(shù)據(jù)列說明,給出每個列的名稱和類型。

read_csv("a,b,c

1,2,3

4,5,6")

#read_csv() 函數(shù)都使用數(shù)據(jù)的第一行作為列名稱,這是一種常見做法。

#? 有時文件開頭會有好幾行元數(shù)據(jù)。你可以使用skip = n來跳過前n行;或者使用 comment = "#" 來丟棄所有以 # 開頭的行:

read_csv("The first line of metadata

? ? ? The second line of metadata

? ? ? x,y,z

? ? ? 1,2,3", skip = 2)

read_csv("# A comment I want to skip

? ? ? x,y,z

? ? ? 1,2,3", comment = "#")

#? 數(shù)據(jù)沒有列名稱??梢允褂胏ol_names = FALSE來通知read_csv()不要將第一行作為列標題,而是將各列依次標注為 X1 至 Xn:

read_csv("1,2,3\n4,5,6", col_names = FALSE)

#"\n" 是非常便捷的快捷方式,用于添加新行

#你也可以向 col_names 傳遞一個字符向量,以用作列名稱

read_csv("1,2,3\n4,5,6", col_names = c("x", "y", "z"))

#另一個通常需要修改的選項是 na。它設(shè)定使用哪個值(或哪些值)來表示文件中的缺失值:

read_csv("a,b,c\n1,2,.", na = ".")

#你肯定很想知道我們?yōu)槭裁床皇褂?read.csv() 函數(shù)

#? 一般來說,它們比基礎(chǔ)模塊中的函數(shù)速度更快(約快 10 倍)。

#? 它們可以生成 tibble,并且不會將字符向量轉(zhuǎn)換為因子,不使用行名稱,也不會隨意改動列名稱。

#? 它們更易于重復(fù)使用。

#解析向量

#parse_*() 函數(shù)族。

#這些函數(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"

#第一個參數(shù)是需要解析的字符向量,

#na 參數(shù)設(shè)定了哪些字符串應(yīng)該當(dāng)作缺失值來處理

parse_integer(c("1", "231", ".", "456"), na = ".")

#> [1] 1 231 NA 456

#如果解析失敗,你會收到一條警告:

? x <- parse_integer(c("123", "345", "abc", "123.45"))

#> Warning: 2 parsing failures.

#> row col expected actual

#解析失敗的值在輸出中是以缺失值的形式存在的

? x

#如果解析失敗的值很多,那么就應(yīng)該使用 problems() 函數(shù)來獲取完整的失敗信息集合。

#這個函數(shù)會返回一個 tibble,你可以使用 dplyr 包來進行處理

? problems(x)

#在解析函數(shù)的使用方面,最重要的是要知道有哪些解析函數(shù),

#以及每種解析函數(shù)用來處理 哪種類型的輸入。

#具體來說,重要的解析函數(shù)有 8 種。

#? parse_logical() 和 parse_integer() 函數(shù)分別解析邏輯值和整數(shù)。因為這兩個解析函數(shù)基本不會出現(xiàn)問題,所以我們不再進行更多介紹。

#? parse_double() 是嚴格的數(shù)值型解析函數(shù),parse_number() 則是靈活的數(shù)值型解析函數(shù)。 這兩個函數(shù)要比你預(yù)想的更復(fù)雜,因為世界各地書寫數(shù)值的方式不盡相同。

#? parse_character() 函數(shù)似乎太過簡單,甚至沒必要存在。但一個棘手的問題使得這個函數(shù)變得非常重要:字符編碼。

#? parse_factor() 函數(shù)可以創(chuàng)建因子,R 使用這種數(shù)據(jù)結(jié)構(gòu)來表示分類變量,該變量具有固定數(shù)目的已知值。

#? parse_datetime()、parse_date() 和 parse_time() 函數(shù)可以解析不同類型的日期和時間。 它們是最復(fù)雜的,因為有太多不同的日期書寫形式。

#數(shù)值

#? 世界各地的人們書寫數(shù)值的方式不盡相同。例如,有些國家使用 . 來分隔實數(shù)中的整數(shù) 和小數(shù)部分,而有些國家則使用 ,。

#? 數(shù)值周圍經(jīng)常有表示某種意義的其他字符,如 $1000 或 10%。

#? 數(shù)值經(jīng)常包含“分組”,以便更易讀,如 1 000 000,而且世界各地用來分組的字符也不盡相同。

#readr 使用了“地區(qū)”這一概念,這是可以按照不同地區(qū)設(shè)置解析選項的一個對象。

#在解析數(shù)值時,最重要的選項就是用來表示小數(shù)點的字符。

#通過創(chuàng)建一個新的地區(qū)對象并設(shè)定 decimal_mark 參數(shù),可以覆蓋 . 的默認值

parse_double("1.23")

parse_double("1,23", locale = locale(decimal_mark = ","))

#readr 的默認地區(qū)是 US-centric,因為 R 是以美國為中心的(也就是說,R 基礎(chǔ)包的文檔是用美式英語寫成的)。

#parse_number() 解決了第二個問題:它可以忽略數(shù)值前后的非數(shù)值型字符。

#這個函數(shù)特別適合處理貨幣和百分比,也可以提取嵌在文本中的數(shù)值:

parse_number("$100")

#> [1] 100

parse_number("20%")

#> [1] 20

parse_number("It cost $123.45")

#> [1] 123

#組合使用 parse_number() 和地區(qū)設(shè)置可以解決最后一個問題,因為 parse_number() 可以忽略“分組符號”:

# 適用于美國

parse_number("$123,456,789")

#> [1] 1.23e+08

# 適用于多數(shù)歐洲國家

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

#字符串

#parse_character() 函數(shù)似乎真的很簡單,只要返回輸入值就可以了。

#問題是生活沒這么簡單,因為同一個字符串有多種表示方式。

#在 R 中,我們可以使用 charToRaw() 函數(shù)獲得一個字符串的底層表示

charToRaw("Hadley")

#> [1] 48 61 64 6c 65 79

#每個十六進制數(shù)表示信息的一個字節(jié):48 是 H、61 是 a 等。

#從十六進制數(shù)到字符的這種映射稱為編碼,這個示例中的編碼方式稱為 ASCII。

#UTF-8 可以為現(xiàn)在人類使用的所有字符進行編碼,同時還支持很多特殊字符(如 表情符號!)

#readr 全面支持 UTF-8:當(dāng)讀取數(shù)據(jù)時,它假設(shè)數(shù)據(jù)是 UTF-8 編碼的,并總是使用 UTF-8 編碼寫入數(shù)據(jù)。

#但對于從不支持 UTF-8 的那些舊系統(tǒng)中產(chǎn)生的數(shù) 據(jù)則無能為力。遇到這種情況時,你的字符串打印出來就是一堆亂碼。

x1 <- "El Ni\xf1o was particularly bad this year"

x2 <- "\x82\xb1\x82\xf1\x82\xc9\x82\xbf\x82\xcd"

#要想解決這個問題,需要在 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ù)來幫助你找出編碼方式。

#希望試驗幾次后,你就能夠找到正確的編碼方式:

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() 的第一個參數(shù)可以是一個文件路徑,也可以是一個原始向量(適用于字 符串已經(jīng)在 R 中的情況),就像本示例一樣。

#因子

#R 使用因子表示取值范圍是已知集合的分類變量。

#如果 parse_factor() 函數(shù)的 levels 參數(shù)被賦予一個已知向量,

#那么只要存在向量中沒有的值,就會生成一條警告:

fruit <- c("apple", "banana")

parse_factor(c("apple", "banana", "bananana"), levels = fruit)

#日期、日期時間與時間

#根據(jù)需要的是日期型數(shù)據(jù)(從 1970-01-01 開始的天數(shù))、

#日期時間型數(shù)據(jù)(從 1970-01-01 午夜開始的秒數(shù)),

#或者是時間型數(shù)據(jù)(從午夜開始的秒數(shù))

#? parse_datetime() 期待的是符合ISO 8601 標準的日期時間。

#ISO 8601 是一種國際標準, 其中日期的各個部分按從大到小的順序排列,即年、月、日、小時、分鐘、秒:

parse_datetime("2010-10-01T2010")

#> [1] "2010-10-01 20:10:00 UTC"

# 如果時間被省略了,那么它就會被設(shè)置為午夜

parse_datetime("20101010")

#> [1] "2010-10-10 UTC"

#這是最重要的日期 / 時間標準

#? parse_date() 期待的是四位數(shù)的年份、一個 - 或 /、月、一個 - 或 /,然后是日:

parse_date("2010-10-01")

#> [1] "2010-10-01"

#? parse_time() 期待的是小時、:、分鐘、可選的 : 和秒,以及一個可選的 a.m./p.m. 標識符:

library(hms)

parse_time("01:10 am")

#> 01:10:00

parse_time("20:10:01")

#> 20:10:01

#找出正確格式的最好方法是創(chuàng)建幾個解析字符向量的示例,并使用某種解析函數(shù)進行測

試。例如:

? 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"

challenge <- read_csv(

? readr_example("challenge.csv"),

? col_types = cols(

? ? x = col_double(),

? ? y = col_date()

? )

)

tail(challenge)

#解析文件

#? readr 如何自動猜出文件每列的數(shù)據(jù)類型。

#? 如何修改默認設(shè)置。

#強烈建議你總是提供 col_types 參數(shù),從 readr 打印出的輸出中可以知道它的值。

#這可以確保數(shù)據(jù)導(dǎo)入腳本的一致性,并可以重復(fù)使用。

#這種方式結(jié)合 type_convert() 函數(shù)使用時特別有效,后者可以在數(shù)據(jù)框的字符列上應(yīng)用啟發(fā)式解析過程

df <- tribble(

? ~x,? ~y,

? "1", "1.21",

? "2", "2.32",

? "3", "4.56"

)

df

type_convert(df)

read_csv("x,y

? ? ? ? 1, 1.21,

? ? ? ? 2, 2.32,

? ? ? ? 3, 4.56",col_types = cols(

? ? ? ? ? x = col_integer(),

? ? ? ? ? y = col_double()))

#write_csv() 和 write_tsv()

#? 它們總是使用 UTF-8 對字符串進行編碼;

#? 它們使用 ISO 8601 格式來保存日期和日期時間數(shù)據(jù),以便這些數(shù)據(jù)不論在何種環(huán)境下都更容易解析。

#如果想要將 CSV 文件導(dǎo)為 Excel 文件,可以使用 write_excel_csv() 函數(shù),

#該函數(shù)會在文件開頭寫入一個特殊字符(字節(jié)順序標記),告訴 Excel 這個文件使用的是 UTF-8 編碼。

#這幾個函數(shù)中最重要的參數(shù)是 x(要保存的數(shù)據(jù)框)和 path(保存文件的位置)。

#na 參數(shù)設(shè)定如何寫入缺失值,如果想要追加到現(xiàn)有的文件,需要設(shè)置 append 參數(shù)

write_csv(challenge, "challenge.csv")

#注意,當(dāng)保存為 CSV 文件時,類型信息就丟失了

#這使得 CSV 文件在暫存臨時結(jié)果時有些不可靠——每次加載時都要重建列類型。

#? write_rds() 和 read_rds() 函數(shù)是對基礎(chǔ)函數(shù) readRDS() 和 saveRDS() 的統(tǒng)一包裝。

#前者可以將數(shù)據(jù)保存為 R 自定義的二進制格式,稱為 RDS 格式

write_rds(challenge, "challenge.rds")

read_rds("challenge.rds")

#feather 包實現(xiàn)了一種快速二進制格式,可以在多個編程語言間共享:

library(feather)

write_feather(challenge, "challenge.feather")

read_feather("challenge.feather")

#feather 要比 RDS 速度更快,而且可以在 R 之外使用。

#RDS 支持列表列(我們將在第 19 章 中介紹),feather 目前還不行。

#其他類型的數(shù)據(jù)

#? haven 可以讀取 SPSS、Stata 和 SAS 文件;

#? readxl 可以讀取 Excel 文件(.xls 和 .xlsx 均可);

#? 配合專用的數(shù)據(jù)庫后端程序(如 RMySQL、RSQLite、RPostgreSQL 等),DBI 可以對相

#應(yīng)數(shù)據(jù)庫進行 SQL 查詢,并返回一個數(shù)據(jù)框。

#對于層次數(shù)據(jù),可以使用 jsonlite(由 JeroenOoms 開發(fā))讀取 JSON 串,使用 xml2 讀取XML 文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類: pyspark.sql...
    mpro閱讀 9,934評論 0 13
  • 1. 基本數(shù)據(jù)導(dǎo)入與readr包應(yīng)用 1.1 基本數(shù)據(jù)導(dǎo)入函數(shù) readr包中的基本導(dǎo)入函數(shù)如下: read_cs...
    100gle閱讀 2,149評論 0 3
  • pyspark.sql module Module context Spark SQL和DataFrames中的重...
    盜夢者_56f2閱讀 5,687評論 0 19
  • 黃河岸邊的花朵 龍鳳嶺下的伙伴 幾十年前的同窗 而今清明的相聚 滿臉笑容的女神 已是奶奶的級別 幸??鞓返臅r光 感...
    風(fēng)雲(yún)藍天閱讀 238評論 0 1
  • 愛情,是什么呢? 或許,你正值青春年少,你期待著那個你想要托付一生的人;或許,你已經(jīng)過了可以輕易說出我愛你這樣的字...
    你樹呀閱讀 441評論 0 1

友情鏈接更多精彩內(nèi)容