Re: [問題]不使用for改使用apply寫法的可能性

看板R_Language作者 (empireisme)時間4年前 (2020/03/26 11:28), 4年前編輯推噓5(5030)
留言35則, 5人參與, 4年前最新討論串4/4 (看更多)
require(magrittr) data(iris) set.seed(1) data <- iris[sample(nrow(iris)) ,] # 打散資料 Xtrain <- data[1:100,1:4] Xtest <- data[101:150,1:4] M <- nrow(Xtrain) N <- nrow(Xtest) distmatrix <- matrix(0,nrow = M,ncol = N) for(i in 1:M){ for(j in 1:N){ distmatrix[i,j]<- sum((Xtrain[i,]-Xtest[j,])^2) %>% sqrt() } } 最近在implement knn 的 distancematrix 想在厚臉皮的問問看 這種常見的操作要怎麼 轉成非迴圈寫法 我用迴圈寫塞的好慢喔 我自己只想到這樣 就卡住了 (matrix(rep(Xtest[1,],nrow(Xtrain)),ncol=ncol(Xtrain),byrow = T)-Xtrain)^2 %>% apply(X=. ,1,sum)%>%sqrt -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 219.91.75.186 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1585193311.A.644.html

03/26 11:38, 4年前 , 1F
避免把 apply 搭配 %>% pipeline 運算子 因為他會把前半部
03/26 11:38, 1F

03/26 11:38, 4年前 , 2F
的向量結果做完才會一個一個丟pipeline 這樣一定超慢(有錯
03/26 11:38, 2F

03/26 11:38, 4年前 , 3F
請指正)
03/26 11:38, 3F

03/26 13:28, 4年前 , 4F
expand.grid和apply一起用可以取代nested loop
03/26 13:28, 4F
params <- expand.grid(M=seq(M), N=seq(N)) distmatrix2 <- matrix(mapply(function(i,j) sqrt(sum((Xtrain[i,]-Xtest[j,])^2)), params$M, params$N), nrow = M, ncol = N) 有點看不懂 mapply這段 有人可以解釋一下他是怎麼運作的嗎 # EQUIVALENT TO OP's distance identical(distmatrix, distmatrix2) 老外的解法 ※ 編輯: empireisme (219.91.75.186 臺灣), 03/26/2020 14:34:27 ※ 編輯: empireisme (219.91.75.186 臺灣), 03/26/2020 14:46:28 ※ 編輯: empireisme (219.91.75.186 臺灣), 03/26/2020 14:58:34

03/26 23:10, 4年前 , 5F
function(i,j)裡的i和j就是params$M和params$N
03/26 23:10, 5F

03/26 23:13, 4年前 , 6F
每做一次function都是拿M和N各一個元素
03/26 23:13, 6F

03/27 10:01, 4年前 , 7F
就此例而言,distmatrix[i, j] <- 改成
03/27 10:01, 7F

03/27 10:01, 4年前 , 8F
rbind(Xtrain[i, ], Xtest[j, ]) %>% dist 會快不少。
03/27 10:01, 8F

03/27 10:28, 4年前 , 9F
或是只有一次dist硬幹 https://i.imgur.com/feLrQO1.jpg
03/27 10:28, 9F

03/27 10:31, 4年前 , 10F
03/27 10:31, 10F

03/27 18:40, 4年前 , 11F
謝a大,但是用dist函數不就代表不能自己定義距離的意
03/27 18:40, 11F

03/27 18:40, 4年前 , 12F
思?
03/27 18:40, 12F

03/27 18:43, 4年前 , 13F
對,但有不少距離定義在R中是由C寫成的。你看看?dist
03/27 18:43, 13F

03/27 18:43, 4年前 , 14F
中的method有沒有你想用的,其它package也有提供
03/27 18:43, 14F

03/27 18:44, 4年前 , 15F
例如生態學家常用的vegan::vegdist()
03/27 18:44, 15F

03/28 03:02, 4年前 , 16F
我想你的寫法會比較慢可能不是用 apply 就能解決。一個一
03/28 03:02, 16F

03/28 03:02, 4年前 , 17F
個算值然後填入矩陣,在R裡面比較沒有效率。可以考慮用矩
03/28 03:02, 17F

03/28 03:02, 4年前 , 18F
陣運算,一次計算完整個 row 再填入矩陣,會會很多。
03/28 03:02, 18F

03/28 19:30, 4年前 , 19F
矩陣運算我就是有點卡住
03/28 19:30, 19F

03/28 20:56, 4年前 , 20F
針對矩陣運算,例如,不要一列對一列算,而是改成一矩
03/28 20:56, 20F

03/28 20:56, 4年前 , 21F
陣對一矩陣算。技巧是你需要額外先造出一堆以列重複的
03/28 20:56, 21F

03/28 20:56, 4年前 , 22F
矩陣使得二個矩陣大小相等而可以直接相減,於是迴圈只
03/28 20:56, 22F

03/28 20:56, 4年前 , 23F
剩一層。效果如何待測試。若有興趣歡迎繼續發文討論。
03/28 20:56, 23F

03/29 00:42, 4年前 , 24F
其實我有做到那邊,在本文的最後一段
03/29 00:42, 24F

03/29 00:42, 4年前 , 25F
但是那時候想說還是有一層迴圈就沒繼續做了
03/29 00:42, 25F

03/29 01:22, 4年前 , 26F
一樣的,你可以創造出兩個非常多重複列但重複方式不同
03/29 01:22, 26F

03/29 01:22, 4年前 , 27F
的大矩陣以達成所以的對應情況,於是完全不用迴圈了。
03/29 01:22, 27F

03/29 01:27, 4年前 , 28F
技巧上可用rep產生不同的重複列號索引來生成二個大矩陣
03/29 01:27, 28F

03/29 01:27, 4年前 , 29F
03/29 01:27, 29F

03/30 13:57, 4年前 , 30F
ok
03/30 13:57, 30F

03/30 14:55, 4年前 , 31F
也許可以這樣寫,在我電腦上其實用 for 的function比較快
03/30 14:55, 31F

03/30 14:55, 4年前 , 32F

03/30 16:51, 4年前 , 33F
抱歉前一大段手邊沒電腦,現在補上
03/30 16:51, 33F

03/30 16:51, 4年前 , 34F

03/30 20:53, 4年前 , 35F
大神們感恩!
03/30 20:53, 35F
文章代碼(AID): #1UV25VP4 (R_Language)
文章代碼(AID): #1UV25VP4 (R_Language)