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 如何更新,不需要重裝的手段進行更新?