Outer()函數


轉載:https://bbs.pinggu.org/thread-7078237-1-1.html

R語言中的outer()函數,名為內積函數,但是他執行的功能並不是解析幾何中的內積。那該函數到底發揮什么功能呢?
我們將分三個部分來探究該函數,其一是outer()函數的傳入參數,其二是outer()函數的運算步驟,其三是拓展舉例。
1.outer()函數的傳入參數
函數格式:outer(x,y,paste或"operator")
1)x和y
x和y可以是向量(vextor)、矩陣(matrix)、數組(array)、數據框(frame)、列表(list)
注:a.此處向量均指列向量
b.常用類型為數值型、字符型、邏輯型。
c.相同類型的向量:v1<-c(1,2,3),v2<-c(4,5,6),則v1和v2為相同類型的向量。而v1<-c(1,2,3),v2<-c("A","B","C"),則v1和v2為不同類型的向量。
那么就存在數據結構:
相同類型的向量->矩陣 不同類型的向量->數據框
相同類型的矩陣->數組 不同類型的向量、矩陣、數據框、列表或者其中任意兩個及以上的組合->列表

2)paste或"operator"
(1)paste表示打印計算結果中元素的組成結構,如:
> outer(1:2,3:5,paste)
[,1] [,2] [,3]
[1,] "1 3" "1 4" "1 5"
[2,] "2 3" "2 4" "2 5"
我們先不考慮outer()函數是如何運算的。

(2)"operator"可以是運算符,包括"+"、"-"、"*"、"/"、"^"等等,需要用雙引號引起來,如:
> outer(1:2,3:5,"*")
也即使用paste打印出來的組成元素兩兩相乘:
[,1] [,2] [,3]
[1,] "1*3" "1*4" "1*5"
[2,] "2*3" "2*4" "2*5"
那么:
> d<-outer(1:2,3:5,"*")
> d
[,1] [,2] [,3]
[1,] 3 4 5
[2,] 6 8 10

2.outer()函數的運算步驟
outer()函數源碼中有一句代碼為:as.vector(X) %*% t(as.vector(Y))
就是說現將傳入參數X和Y先轉換成向量,其中Y轉換成向量后還要對其進行轉置。
注:a.此處向量均指列向量
b.矩陣轉換成向量時,先按行遍歷矩陣的第一列,然后按行遍歷矩陣的第二列,以此類推直到遍歷完矩陣的所有元素。(從上到下,從左到右)
如矩陣d:
[,1] [,2] [,3]
[1,] 3 4 5
[2,] 6 8 10
轉換成向量為:(3,6,4,8,5,10)T
那么outer(1:2,3:5,"*")就在執行:
第一步:生成x和y向量
_ _ _ _
x=| 1 | y= | 3 |
|_ 2 _| | 4 |
|_ 5 _|

第二步:將y轉換成向量,y本身就是向量,因而轉換后形式不變。
第三步:將y轉置,此時
_ _
x=| 1 | yT=[3,4,5]
|_ 2 _|

第四步:執行x %*% yT 運算(%*%運算與矩陣的乘法運算存在差異,一定不能搞混淆了)
先將x看成一個常數k,用k分別乘以yT中的每個元素,則得到向量[k*3,k*4,k*5]
將k打開,得到矩陣結構:
_ _
| 1*3 1*4 1*5 |
|_ 2*3 2*4 2*5 _|

分別計算矩陣中每一個元素的乘積,得到:
_ _
| 3 4 5 |
|_ 6 8 10 _|

3.拓展舉例
我們在R軟件的控制台中執行如下代碼。
> d<-outer(1:2,3:5,"*")
> d
[,1] [,2] [,3]
[1,] 3 4 5
[2,] 6 8 10
將得到d矩陣,那么在R軟件的控制台中繼續執行
> dd<-outer(d,d,"*")
> dd
將得到什么呢?
此時:
_ _
d=| 3 4 5 |
|_ 6 8 10 _|

還是按上述步驟執行
第一步:輸入兩個d向量,則兩個d向量分別為:
_ _ _ _
d=| 3 4 5 | d=| 3 4 5 |
|_ 6 8 10 _| |_ 6 8 10 _|

第二和第三步:將第二個矩陣d轉換成向量,並將其轉置,得到
_ _
d=| 3 4 5 | d'=[3,6,4,8,5,10]
|_ 6 8 10 _| 位於原矩陣d的1行1列,

其中d'=[3,6,4,8,5,10],第一個元素3位於原矩陣(第二個矩陣d)的1行1列,記為(1,1);第而個元素6位於原矩陣的2行1列,記為(2,1);以此類推。

第四步:執行x %*% yT 運算
先將第一個矩陣d看成一個常數k,用k分別乘以第二個向量d'中的每個元素得到[k*3,k*6,k*4,k*8,k*5,k*10]
將k打開,得到矩陣結構:
_ _
| _ _ _ _ _ _ _ _ _ _ _ _ |
| | 3 4 5 |*3, | 3 4 5 |*6, | 3 4 5 |*4, | 3 4 5 |*8, | 3 4 5 |*5, | 3 4 5 |*10 |
| |_ 6 8 10 _| |_ 6 8 10 _| |_ 6 8 10 _| |_ 6 8 10 _| |_ 6 8 10 _| |_ 6 8 10 _| |
|_ _|
3位於第二個矩陣d 6位於第二個矩陣d 4位於第二個矩陣d 8位於第二個矩陣d 5位於第二個矩陣d 10位於第二個矩陣d
的1行1列記為(1,1) 的2行1列記為(2,1) 的1行2列記為(1,2) 的2行2列記為(2,2) 的1行3列記為(1,3) 的2行3列記為(2,3)

然后將各元素乘進去得到:
_ _
| _ _ _ _ _ _ _ _ _ _ _ _ |
| | 3*3 4*3 5*3 |,| 3*6 4*6 5*6 |,| 3*4 4*4 5*4 |,| 3*8 4*8 5*8 |,| 3*5 4*5 5*5 |,| 3*10 4*10 5*10 | |
| |_6*3 8*3 10*3_| |_6*6 8*6 10*6_| |_6*4 8*4 10*4_| |_6*8 8*8 10*8_| |_ 6*5 8*5 10*5_| |_6*10 8*10 10*10_| |
|_ _|

由於第一個矩陣d為二維矩陣,且運算時將其看成一個常數,因而其維數被R語言省略掉了,控制台並沒有顯示其維數,只用",,"來表示。R控制台中執行:
> outer(d,d,paste)
, , 1, 1 對應第四步中的矩陣下標(1,1)

[,1] [,2] [,3]
[1,] "3 3" "4 3" "5 3"
[2,] "6 3" "8 3" "10 3"

, , 2, 1 對應第四步中的矩陣下標(2,1)

[,1] [,2] [,3]
[1,] "3 6" "4 6" "5 6"
[2,] "6 6" "8 6" "10 6"

, , 1, 2 對應第四步中的矩陣下標(1,2)

[,1] [,2] [,3]
[1,] "3 4" "4 4" "5 4"
[2,] "6 4" "8 4" "10 4"

, , 2, 2 對應第四步中的矩陣下標(2,2)

[,1] [,2] [,3]
[1,] "3 8" "4 8" "5 8"
[2,] "6 8" "8 8" "10 8"

, , 1, 3 對應第四步中的矩陣下標(1,3)

[,1] [,2] [,3]
[1,] "3 5" "4 5" "5 5"
[2,] "6 5" "8 5" "10 5"

, , 2, 3 對應第四步中的矩陣下標(2,3)

[,1] [,2] [,3]
[1,] "3 10" "4 10" "5 10"
[2,] "6 10" "8 10" "10 10"

因而R控制台中執行
> dd<-outer(d,d,"*")
> dd
, , 1, 1 對應第四步中的矩陣下標(1,1)

[,1] [,2] [,3]
[1,] 9 12 15
[2,] 18 24 30

, , 2, 1 對應第四步中的矩陣下標(2,1)

[,1] [,2] [,3]
[1,] 18 24 30
[2,] 36 48 60

, , 1, 2 對應第四步中的矩陣下標(1,2)

[,1] [,2] [,3]
[1,] 12 16 20
[2,] 24 32 40

, , 2, 2 對應第四步中的矩陣下標(2,2)

[,1] [,2] [,3]
[1,] 24 32 40
[2,] 48 64 80

, , 1, 3 對應第四步中的矩陣下標(1,3)

[,1] [,2] [,3]
[1,] 15 20 25
[2,] 30 40 50

, , 2, 3 對應第四步中的矩陣下標(2,3)

[,1] [,2] [,3]
[1,] 30 40 50
[2,] 60 80 100


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM