如何用R語言計算形態坐標矩陣的質心距離?

首先,題圖來自網路,這個問題來源於前幾天第一次在值乎上被人提問,回答了別人的問題,自己也有所得,寫點東西做個記錄。

兩個概念

  • 形態坐標矩陣:在一個mtimes n維的矩陣當中,n為偶數,每一行代表一個樣本,每一行的列依次為該樣本的x, y坐標,比如第一行前四列的意思就是第一個樣本的兩組坐標(left( x_{1}, y_{1}  right) ,left( x_{2}, y_{2}  right)

  • 質心距離:物理上的定義是不同物體質心與質心之間的距離。通常在K-means聚類演算法當中,人為初始化K個質心並確定待分類的數據的類數,然後通過歐幾里得距離公式計算質心距離。

在R語言中,shapes包中的centroid.size()函數可以計算質心距離。

數據導入

#導入包nlibrary(xlsx)nlibrary(shapes)n#載入需要的程輯包:rJavan#載入需要的程輯包:xlsxjarsn#導入數據nsemi <- read.xlsx("G:/workspace/Semi/semi.xls",1, head = FALSE, encoding = "UTF-8")n

因為原始數據是excel文件,這裡採用xlsx包,原始數據無列名,因此直接設置 head = FALSE。

數據處理

因為centroid.size()接受矩陣格式的數據輸入,因此首先將數據從數據框轉化為矩陣。

#將數據框轉換為矩陣nsemi_2D <- as.matrix(semi)n

考慮到本問題的核心就是將一行包含形態坐標的數據轉換成一個列數為2的矩陣,並且原數據已經是若干行的矩陣,因此最終轉換後的數據應該是一個三維數組。下面首先構造三維數組並初始化為0:

#構造三維數組並初始化為0nsemi_3D <- array(0,dim = c(dim(semi_2D)[1],2,dim(semi_2D)[2]/2))n

然後將原來semi_2D中每一行的數據分別賦值給semi_3D的兩列,並且考慮到semi_2D原來的數據類型是char,為了後續計算,將其轉化成numeric。代碼如下:

#將每一行數據轉換成兩列的坐標,並且將char數據轉化成numeric數據nfor (i in 1:dim(semi_2D)[1]) {n for (j in 1:dim(semi_2D)[2]) {n semi_3D[i,(j + 1) %% 2 + 1,(j + 1) %/% 2] <- as.numeric(semi_2D[i,j])n }n}n

到此,形態坐標矩陣的轉換工作已經完畢。

結果計算

首先,創建質心距離的保存變數,因為有n行形態坐標樣本,因此有n個數據,這裡創建一個向量:

#設置質心距離保存向量nDistance <- c(dim(semi_3D[1]))n

然後調用centroid.size()函數計算三維數組當中每一組坐標數據的質心距離,需要注意的是調用的時候需要將數據進行轉置,矩陣的轉置可以採用t()函數。

#計算質心距離,每一次需要將semi_3D[i,,]矩陣進行轉置nlibrary(shapes)nfor (i in 1:dim(semi_3D)[1]) {n Distance[i] <- centroid.size(t(semi_3D[i,,]))n}n

圖形展示

mycolors <- rainbow(60)nbarplot(Distance,n main = "不同樣本質心距離圖",n xlab = "樣本編號",n ylab = "質心距離",n col = mycolors)n

上圖展示了不同編號的質心距離的編號。

小結

雖然問題比較簡單,不過解決問題的思路都是類似的,首先將大的問題分解為幾個小問題,然後一個一個分別攻破,比如本例中的數據導入、數據類型的轉換、數據形式的轉換(以一維到二維)到最後調用已有的包計算質心距離。當然,如果沒有現成的包,自己編寫程序計算也是可行的,下文:

多邊形centroid的計算方法 · jingsam

可以參考用來計算若干個二維平面質心距離的計算。

PS:這幾天發現了一個小竅門,在值乎中輸入代碼時提示選擇是什麼語言,因為沒有R所以之前都沒有設置,但是因為R是延伸自S的,所以設置成S語言代碼的關鍵字和顏色什麼的跟R基本差不多。


推薦閱讀:

【詐屍譯文】R 3.4.0的性能提升
[譯] 解密 Airbnb 的數據科學部門如何構建知識倉庫
僅用四行代碼就可以挖掘你的QQ聊天記錄
數據分析利器之dplyr、ggplot2包
Learn R | 字元串處理之stringr包(上)

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