R語言編程技術3(轉載)

本文經作者同意R語言編程技術(3) - 飛貓俠的博客 - CSDN博客轉載。

上節反覆的強調了 數據結構 對於編程的重要性,儘管 R語言 不算工程性語言,但是如果熟練掌握了它內置的數據結構,那麼做起數據處理的任務就能遊刃有餘,你並不需要知道什麼是 鏈表 ,什麼是 二叉樹 ,什麼是 散列表 ,

但是你要知道什麼是 向量 ,什麼是 列表 ,什麼是 矩陣 ,什麼是 數據框。(好像還少了個什麼?),沒錯就是這節的主角 多維數組 , 之前按照數據維度和結構特性將 R語言 的 數據結構 進行了列表劃分,就是上述的五種 數據結構 , 事實上高度總結一下就兩種類型的結構。

存放類型

數據結構

必須存放同類型

向量,矩陣,數組

可存放不同類型

列表,數據框

上節有說明其實 列表 和 數據框 是等價互換的,本質上只是 列表 的一種變形,本節要闡明一個觀點,向量,矩陣,數組 其實也是等價的互換的,只是發生了維度的變換而已,代碼說話時間。 使用 c 與 matrix 函數來創建向量和矩陣:

# 創建一個向量

c(1:10)

# [1] 1 2 3 4 5 6 7 8 9 10

# 創建一個 2x5 的矩陣

matrix(1:10, 2, 5)

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

使用 array 函數來創建向量和矩陣:

# 創建一個向量

array(1:10)

# [1] 1 2 3 4 5 6 7 8 9 10

# 創建一個 2x5 的矩陣

array(c(1:10), dim = c(2, 5))

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

這裡可以理解成 向量 和 矩陣 就是 數組 的特殊情況(雖然我覺得屬於常識,但是還是要特彆強調一下),只是 R

語言 提供了專門創建和向量 和 矩陣 的內置函數而已,這裡可以聯想到 Python 的 numpy 包當中的創建多維數組的 array 函數(畢竟大家是同門師兄弟嘛)。

import numpy as np

# 創建一維數組並列印

print np.array(range(1, 11))

# [ 1 2 3 4 5 6 7 8 9 10]

# 創建二維數組並列印

print np.array(range(1, 11)).reshape((2,5))

# [[ 1 2 3 4 5]

# [

6 7 8 9 10]]

註:不明白python代碼也木有關係,只是為了做一個對比參照來說明問題而已。 那麼由此可以得到一個顯而易見的結論 向量 就是一維數組, 矩陣 是二維數組,只是它們屬於動態數組。(解釋性語言當然是動態的啦~~)

在實際的工作當中其實很少用到 R 的多維數組,而最頻繁使用的是數據框。正因為用的少,所以很容易被遺忘,以至於它的基本性能可能都罕為人知,但是它畢竟是基礎,夯實基礎可以以不變應萬變。 二維數組取子集:

# 創建一個 2x5 的矩陣

array(1:10,

dim = c(2,5))

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

# 取矩陣第一列

array(1:10, dim = c(2,5))[, 1]

# [1] 1 2

# 取矩陣第一行

array(1:10, dim = c(2,5))[1, ]

# [1] 1 3 5 7 9

# 取第一行第四列元素

array(1:10, dim = c(2,5))[1, 4]

# [1] 7

三維數組取子集:

# 創建一個 2x5x2 的三維數組

# 這裡可以理解創建了兩個不同的空間來存放相同的矩陣

array(1:10, dim = c(2,5,2))

# , , 1

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

# , , 2

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

# 取第一空間里的矩陣

array(1:10,

dim = c(2,5,2))[, , 1]

# [,1] [,2] [,3] [,4] [,5]

# [1,] 1 3 5 7 9

# [2,] 2 4 6 8 10

# 取所有空間下矩陣的第一行

array(1:10, dim = c(2,5,2))[1, , ]

[,1]

[,2]

[1,] 1 1

[2,] 3 3

[3,] 5 5

[4,] 7 7

[5,] 9 9

# 取所有空間下矩陣的第一列

array(1:10, dim = c(2,5,2))[, 1, ]

[,1]

[,2]

[1,] 1 1

[2,] 2 2

如果這裡沒有被弄暈,說明你的空間想像能力還是過關的,下面我們嘗試一下對更高維度的解釋。代碼說話:

# 創建一個 2x2x3x2 的四維數組

array(1:4, dim = c(2,2,3,2))

# , , 1, 1

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

#

# , , 2, 1

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

#

# , , 3, 1

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

#

# , , 1, 2

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

#

# , , 2, 2

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

#

# , , 3, 2

#

# [,1] [,2]

# [1,] 1 3

# [2,] 2 4

聰明的你會發現,把一個同樣的矩陣列印了 6 次是什麼鬼?因為最初給定的數據只有1:4四個元素,該數據被按列映射到 2 x 2 的矩陣中,當添加了兩個新的維度,這裡可以把 2 x 2 的矩陣看作一個整體,因為 R 的 循環填充 機制這個整體被循環填充到了一個新的 3 x 2新矩陣下,因為順序列印的關係就出現了如上 6 個相同的矩陣。 將這個高維數組做拉直運算:

# 拉直運算

as.vector(array(1:4, dim = c(2,2,3,2)))

# [1] 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3

4 1 2 3 4

# 計算倍數

length(as.vector(array(1:4, dim = c(2,2,3,2))))/4

# [1] 6

高維數組被拉直為一個向量,此向量的長度就是維度向量的乘積 2 * 2 * 3 * 2 = 24,而數據事實上是被 循環填充 了 6 次,按照上述把小矩陣看作一個整體在映射到新的 3 x 2 矩陣下:

ai=[1234]

b=????a1a2a3a3a4a5????

如此就可以等價表示為一個 6 x 4 的矩陣了,如此一來四維數組又被轉換成二維數組了,若對二維的數組做拉直運算,又被變換成一維的了,對一維數組求個和又變成單值了(事實上R當中沒有標量,最小單位就是長度為一的向量,這裡只是說成單值而已)

# 重構一個6X4的矩陣

array(as.vector(array(1:4, dim = c(2,2,3,2))),

dim=c(6,4))

# [,1] [,2] [,3] [,4]

# [1,] 1 3 1 3

# [2,] 2 4 2 4

# [3,] 3 1 3 1

# [4,] 4 2 4 2

# [5,] 1 3 1 3

# [6,] 2 4 2 4

# 對新矩陣做拉直運算

as.vector(array(as.vector(array(1:4, dim =

c(2,2,3,2))), dim=c(6,4)))

# [1] 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3

4 1 2 3 4

# 對拉直向量求和

sum(as.vector(array(as.vector(array(1:4,

dim = c(2,2,3,2))), dim=c(6,4))))

# [1] 60

註:上述代碼中函數的多層套用只是為了說明問題,具體寫代碼時不建議這樣操作。 是不是頓時覺得世界如此奇妙,最後再引用一段很玄妙的話。 道生一,一為太極;一生二,二為兩儀;二生四,四為四象;四生八,八為八卦;八卦生六十四,六十四具而後天地之數備焉。天地萬物莫不以一為本原,於一而演之以萬,窮天下之數而復歸於一。 總結下來就是 萬變不離其宗 。因為數據也屬於是萬物的一部分,故而也遵循這個規律


推薦閱讀:

好看的數據可視化的圖片是怎麼樣做的?
如何高效的在R里寫出一個循環?
經常做報表數據分析希望通過編程來實現部分辦公自動化,作為零基礎編程的人,哪種語言易於上手?
如何使用 ggplot2 ?
r 如何更新,不需要重裝的手段進行更新?

TAG:R编程语言 | 编程 | 数据分析 |