《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note14:向量

向量.jpg

寫在前面

本系列為《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宜雀、TRUENA切平。 一般可以通過比較運算符來構(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 個特殊值:NANaN寂祥、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ù)來返回 TRUEFALSE

檢驗函數(shù)

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钮热、tbldata.frame。它的特性有 2 個:(列)namesrow.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)行管道操作

《R數(shù)據(jù)科學(xué)》學(xué)習(xí)筆記|Note11:使用forcats處理因子

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蛀骇,一起剝皮案震驚了整個濱河市厌秒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌擅憔,老刑警劉巖鸵闪,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暑诸,居然都是意外死亡蚌讼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門个榕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篡石,“玉大人,你說我怎么就攤上這事西采』巳” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長胖眷。 經(jīng)常有香客問我武通,道長,這世上最難降的妖魔是什么珊搀? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任冶忱,我火速辦了婚禮,結(jié)果婚禮上境析,老公的妹妹穿的比我還像新娘囚枪。我一直安慰自己,他們只是感情好簿晓,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布眶拉。 她就那樣靜靜地躺著,像睡著了一般憔儿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上放可,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天谒臼,我揣著相機與錄音,去河邊找鬼耀里。 笑死蜈缤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的冯挎。 我是一名探鬼主播底哥,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼房官!你這毒婦竟也來了趾徽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤翰守,失蹤者是張志新(化名)和其女友劉穎孵奶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜡峰,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡了袁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了湿颅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片载绿。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖油航,靈堂內(nèi)的尸體忽然破棺而出崭庸,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布冀自,位于F島的核電站揉稚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏熬粗。R本人自食惡果不足惜搀玖,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驻呐。 院中可真熱鬧灌诅,春花似錦、人聲如沸含末。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽佣盒。三九已至挎袜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肥惭,已是汗流浹背盯仪。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜜葱,地道東北人全景。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像牵囤,于是被迫代替她去往敵國和親爸黄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容