寫在前面
本系列為《R數(shù)據(jù)科學(xué)》(R for Data Science)的學(xué)習(xí)筆記流酬。相較于其他R語言教程來說回官,本書一個很大的優(yōu)勢就是直接從實用的R包出發(fā),來熟悉R及數(shù)據(jù)科學(xué)城榛。更新過程中揪利,讀者朋友如發(fā)現(xiàn)錯誤,歡迎指正吠谢。如果有疑問土童,也可以后臺私信。希望各位讀者朋友能學(xué)有所得工坊!
向量
14.1 向量基礎(chǔ)
向量的類型主要有兩種献汗。
- 原子向量,其共有 6 種類型:邏輯型王污、整型罢吃、雙精度型、字符型昭齐、復(fù)數(shù)型和原始型尿招。整型和雙精度型向量又統(tǒng)稱為數(shù)值型向量。
- 列表阱驾,有時又稱為遞歸向量就谜,因為列表中也可以包含其他列表。
原子向量與列表之間的主要區(qū)別是里覆,原子向量中的各個值都是同種類型的丧荐,而列表中的各個值可以是不同類型的。NULL
是一個與向量相關(guān)的對象喧枷,用于表示空向量(與表示向量中的一個值為空的 NA
不同)虹统,通常指長度為 0 的向量。
每個向量都有兩個關(guān)鍵屬性隧甚。
- 類型车荔。可以使用
typeof()
函數(shù)來確定向量的類型:
typeof(letters)
> [1] "character"
typeof(1:10)
> [1] "integer"
- 長度戚扳∮潜悖可以使用
length()
函數(shù)來確定向量的長度:
x <- list("a", "b", 1:10)
length(x)
> [1] 3
14.2 重要的原子向量
4 種最重要的原子向量類型是邏輯型、整型帽借、雙精度型和字符型珠增。
14.2.1 邏輯型
邏輯型向量是最簡單的一種原子向量,因為它們只有 3 個可能的取值:FALSE
宜雀、TRUE
和 NA
切平。 一般可以通過比較運算符來構(gòu)建邏輯向量。還可以通過 c()
函數(shù)來手工創(chuàng)建邏輯向量:
1:10 %% 3 == 0
> [1] FALSE FALSE TRUE FALSE FALSE
> [2] TRUE FALSE FALSE TRUE FALSE
c(TRUE, TRUE, FALSE, NA)
> [1] TRUE TRUE FALSE NA
14.2.2 數(shù)值型
整型與雙精度型向量統(tǒng)稱為數(shù)值型向量辐董。R 中默認(rèn)數(shù)值是雙精度型的悴品。如果想要創(chuàng)建整型數(shù)值,可以在數(shù)字后面加一個 L
:
typeof(1)
> [1] "double"
typeof(1L)
> [1] "integer"
1.5L
> [1] 1.5
- 雙精度型是近似值简烘。雙精度型表示的是浮點數(shù)苔严,不能由固定數(shù)量的內(nèi)存精確表示。這意味著你應(yīng)該將所有雙精度數(shù)當(dāng)成近似值孤澎。eg:
x <- sqrt(2) ^ 2 #2的平方根的平方
x
> [1] 2
x - 2
> [1] 4.44e-16
在比較浮點數(shù)時届氢,不能使用 ==
,而應(yīng)該使用 dplyr::near()
覆旭,后者可以容忍一些數(shù)據(jù)誤差退子。
- 整型數(shù)據(jù)有 1 個特殊值
NA
岖妄,而雙精度型數(shù)據(jù)則有 4 個特殊值:NA
、NaN
寂祥、Inf
和-Inf
荐虐。 其他 3 個特殊值都可以由除法產(chǎn)生:
c(-1, 0, 1) / 0
> [1] -Inf NaN Inf
不要使用 ==
來檢查這些特殊值,而應(yīng)該使用輔助函數(shù) is.finite()
丸凭、is.infinite()
和 is.nan()
福扬。
14.2.3 字符型
字符向量每個元素都是一個字符串,可以包含任意數(shù)量的數(shù)據(jù)惜犀。
14.2.4 缺失值
每種類型的原子向量都有自己的缺失值:
NA # 邏輯型
> [1] NA
NA_integer_ # 整型
> [1] NA
NA_real_ # 雙精度型
> [1] NA
NA_character_ # 字符型
> [1] NA
14.3 使用原子向量
14.3.1 強制轉(zhuǎn)換
將一種類型的向量強制轉(zhuǎn)換成另一種類型的方式有兩種铛碑。
- 顯式強制轉(zhuǎn)換:當(dāng)調(diào)用
as.logical()
、as.integer()
虽界、as.double()
或as.character()
這樣的函數(shù)進(jìn)行轉(zhuǎn)換時汽烦,使用的就是顯式強制轉(zhuǎn)換。 - 隱式強制轉(zhuǎn)換:當(dāng)在特殊的上下文環(huán)境中使用向量浓恳,而這個環(huán)境又要求使用特定類型的 向量時刹缝,就會發(fā)生隱式強制轉(zhuǎn)換。
常見的隱式強制轉(zhuǎn)換:在數(shù)值環(huán)境中使用邏輯向量颈将。這種情況下梢夯,TRUE
轉(zhuǎn)換為 1,FALSE
轉(zhuǎn)換為 0晴圾。這意味著對邏輯向量求和的結(jié)果就是其中真值的個數(shù)颂砸,邏輯向量的均值就是其中真值的比例:
x <- sample(20, 100, replace = TRUE)
y <- x > 10
sum(y) # 大于10的數(shù)有多少個?
> [1] 44
mean(y) # 大于10的數(shù)的比例是多少死姚?
> [1] 0.44
14.3.2 檢驗函數(shù)
檢驗向量類型的一種方法是使用 typeof()
函數(shù)人乓,另一種方法是使用檢驗函數(shù)來返回 TRUE
或 FALSE
。
14.3.3 標(biāo)量與循環(huán)規(guī)則
R 可以對向量長度進(jìn)行強制轉(zhuǎn)換都毒。這種轉(zhuǎn)換稱為向量循環(huán)色罚,因為 R 會將較短的向量重復(fù)(或稱循環(huán))到與較長的向量相同的長度。為 R 中沒有真正的標(biāo)量账劲,只有長度為 1 的向量戳护。
兩個長度不同的向量相加:
1:10 + 1:2
> [1] 2 4 4 6 6 8 8 10 10 12
R 會擴展較短的向量,使其與較長的向量一樣長瀑焦,這個過程就稱作向量循環(huán)腌且。這個過程是默默進(jìn)行的,除非較長向量的長度不是較短向量長度的整數(shù)倍:
> 1:10 + 1:3
[1] 2 4 6 5 7 9 8 10 12 11
Warning message:
In 1:10 + 1:3 : 長的對象長度不是短的對象長度的整倍數(shù)
雖然可以創(chuàng)建非常簡潔優(yōu)雅的代碼榛瓮,但向量循環(huán)也可以悄無聲息地掩蓋某些問題铺董。為此, 只要循環(huán)的不是一個標(biāo)量禀晓,那么 tidyverse
中的向量化函數(shù)就會拋出一條錯誤消息精续。如果確實想要執(zhí)行向量循環(huán)坝锰,那么你需要使用 rep()
函數(shù)手工完成:
> tibble(x = 1:4, y = 1:2)
Error: Variables must be length 1 or 4.
Problem variables: 'y'
> tibble(x = 1:4, y = rep(1:2, 2))
# A tibble: 4 x 2
x y
<int> <int>
1 1 1
2 2 2
3 3 1
4 4 2
> tibble(x = 1:4, y = rep(1:2, each = 2))
# A tibble: 4 x 2
x y
<int> <int>
1 1 1
2 2 1
3 3 2
4 4 2
14.3.4 向量命名
所有類型的向量都是可以命名的。使用 c()
函數(shù)創(chuàng)建向量時進(jìn)行命名:
c(x = 1, y = 2, z = 4)
> c(x = 1, y = 2, z = 4)
x y z
1 2 4
也可以在向量創(chuàng)建完成后驻右,使用 purrr::set_names()
函數(shù)來命名:
> set_names(1:3, c("a", "b", "c"))
a b c
1 2 3
14.3.5 向量取子集
[
就是取子集函數(shù)什黑,調(diào)用形式是 x[a]
崎淳。
- 使用僅包含整數(shù)的數(shù)值向量堪夭。整數(shù)要么全部為正數(shù),要么全部為負(fù)數(shù)拣凹,或者為 0森爽。 使用正整數(shù)取子集時,可以保持相應(yīng)位置的元素:
x <- c("one", "two", "three", "four", "five")
x[c(3, 2, 5)]
> [1] "three" "two" "five"
# 位置可以重復(fù)嚣镜,這樣可以生成比輸入更長的輸出結(jié)果:
x[c(1, 1, 5, 5, 5, 2)]
> [1] "one" "one" "five" "five" "five" "two"
#使用負(fù)整數(shù)取子集時爬迟,會丟棄相應(yīng)位置的元素:
x[c(-1, -3, -5)]
#> [1] "two" "four"
#正數(shù)與負(fù)數(shù)混合使用則會引發(fā)一個錯誤:
> x[c(1, -1)]
Error in x[c(1, -1)] : 只有負(fù)下標(biāo)里才能有零
- 使用邏輯向量取子集。這種方式可以提取出
TRUE
值對應(yīng)的所有元素菊匿,一般與比較函數(shù)結(jié)合起來使用效果最佳:
x <- c(10, 3, NA, 5, 8, 1, NA)
# x中的所有非缺失值
x[!is.na(x)]
> [1] 10 3 5 8 1
# x中的所有偶數(shù)值(或缺失值)
x[x %% 2 == 0]
> [1] 10 NA 8 NA
- 如果是命名向量付呕,那么可以使用字符向量來取子集:
x <- c(abc = 1, def = 2, xyz = 5)
x[c("xyz", "def")]
> x[c("xyz", "def")]
xyz def
5 2
- 取子集的最簡方式就是什么都不寫:
x[]
,這樣就會返回 x 中的全部元素跌捆。對于矩陣(或其他高維數(shù)據(jù)結(jié)構(gòu))這樣可以取出所有的行或所有的列徽职,只要將行或列保持為空即可。例如佩厚,如果x
是 二維的姆钉,那么x[1, ]
可以選取出第 1 行和所有列,x[, -1]
則可以選取出所有行和除第 1 列外的所有列抄瓦。
14.4 遞歸向量(列表)
可以使用 list()
函數(shù)創(chuàng)建列表:
x <- list(1, 2, 3)
x
> x
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
在處理列表時潮瓶,str()
函數(shù)是一個非常有用的工具,因為其重點關(guān)注列表結(jié)構(gòu)钙姊,而不是列表內(nèi)容:
str(x)
> str(x)
List of 3
$ : num 1
$ : num 2
$ : num 3
x_named <- list(a = 1, b = 2, c = 3)
str(x_named)
> str(x_named)
List of 3
$ a: num 1
$ b: num 2
$ c: num 3
與原子向量不同毯辅,list()
中可以包含不同類型的對象:
> y <- list("a", 1L, 1.5, TRUE)
> str(y)
List of 4
$ : chr "a"
$ : int 1
$ : num 1.5
$ : logi TRUE
14.4.1 列表可視化
x1 <- list(c(1, 2), c(3, 4))
x2 <- list(list(1, 2), list(3, 4))
x3 <- list(1, list(2, list(3)))
可以用以下圖形來表示它們:
這種可視化表示遵循以下 3 個原則。
- 列表用圓角矩形表示煞额,原子向量用直角矩形表示思恐。
- 子向量繪制在父向量中,而且背景要比父向量深一些立镶,這樣更容易表示出層次結(jié)構(gòu)壁袄。
- 子向量的方向(也就是其行和列)并不重要,我們只在示例中表示出一行或一列媚媒。
14.4.2 列表取子集
列表取子集有 3 種方式:
a <- list(a = 1:3, b = "a string", c = pi, d = list(-1, -5))
> a
$a
[1] 1 2 3
$b
[1] "a string"
$c
[1] 3.141593
$d
$d[[1]]
[1] -1
$d[[2]]
[1] -5
- 使用
[
提取子列表嗜逻。
> str(a[1:2])
List of 2
$ a: int [1:3] 1 2 3
$ b: chr "a string"
> str(a[4])
List of 1
$ d:List of 2
..$ : num -1
..$ : num -5
- 使用
[[
從列表中提取單個元素。
> str(a[[1]])
int [1:3] 1 2 3
> str(a[[4]])
List of 2
$ : num -1
$ : num -5
-
$
是提取列表命名元素的簡單方式缭召,其作用與[[
相同栈顷,只是不需要使用括號:
> a$a
[1] 1 2 3
> a[["a"]]
[1] 1 2 3
對于列表來說逆日,[
和 [[
之間的區(qū)別是非常重要的,因為 [[
會使列表降低一個層級萄凤,而 [
則會返回一個新的室抽、更小的列表。如下圖所示:
14.5 擴展向量
原子向量和列表是最基礎(chǔ)的向量靡努,使用它們可以構(gòu)建出另外一些重要的向量類型坪圾,比如因子和日期。我們稱構(gòu)建出的這些向量為擴展向量惑朦,因為它們具有附加特性兽泄,其中包括類。 因為擴展向量中帶有類漾月,所以它們的行為就與基礎(chǔ)的原子向量不同病梢。如:
- 因子
- 日期
- 日期時間
- tibble
14.5.1 因子
因子是設(shè)計用來表示分類數(shù)據(jù)的,只能在固定集合中取值梁肿。因子是在整型向量的基礎(chǔ)上構(gòu)建的蜓陌,添加了水平特性:
> x <- factor(c("ab", "cd", "ab"), levels = c("ab", "cd", "ef"))
> x
[1] ab cd ab
Levels: ab cd ef
> typeof(x)
[1] "integer"
> attributes(x)
$levels
[1] "ab" "cd" "ef"
$class
[1] "factor"
14.5.2 日期和日期時間
R 中的日期是一種數(shù)值型向量,表示從 1970 年 1 月 1 日開始的天數(shù)
> x <- as.Date("1971-01-01")
> x
[1] "1971-01-01"
> typeof(x)
[1] "double"
> attributes(x)
$class
[1] "Date
14.5.3 tibble
tibble
是擴展的列表吩蔑,有 3 個類:tbl_df
钮热、tbl
和 data.frame
。它的特性有 2 個:(列)names
和 row.names
哥纫。
> tb <- tibble::tibble(x = 1:5, y = 5:1)
> tb
# A tibble: 5 x 2
x y
<int> <int>
1 1 5
2 2 4
3 3 3
4 4 2
5 5 1
> typeof(tb)
[1] "list"
> attributes(tb)
$names
[1] "x" "y"
$row.names
[1] 1 2 3 4 5
$class
[1] "tbl_df" "tbl" "data.frame"
傳統(tǒng) data.frames
具有非常相似的結(jié)構(gòu):
> df <- data.frame(x = 1:5, y = 5:1)
> df
x y
1 1 5
2 2 4
3 3 3
4 4 2
5 5 1
> typeof(df)
[1] "list"
> attributes(df)
$names
[1] "x" "y"
$class
[1] "data.frame"
$row.names
[1] 1 2 3 4 5
tibble
的類包括了 data.frame
霉旗,這說明 tibble
自動繼承了普通數(shù)據(jù)框的行為。
往期內(nèi)容:
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note13:函數(shù)
《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note12:使用magrittr進(jìn)行管道操作