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

看板R_Language作者 (天)時間4年前 (2020/03/26 09:31), 4年前編輯推噓1(102)
留言3則, 1人參與, 4年前最新討論串3/4 (看更多)
※ 引述《locka (locka)》之銘言: : (同是apply家族愛好者先shout out一下XD) : 以前看過版主C大跟其他前輩版友的討論,結論是 apply 效率並沒有比較好 : (印象中好像背後都還是用for迴圈?!) : 不過我覺得向量化(vectorized)是R語言裡面很重要的一個特性 : 也是functional programming跟其他程式語言不一樣的地方 : 我自己也喜歡做for轉apply的練習 : === 分隔線 === : 以下的寫法只是隨便寫的(甚至可以說骨子裡還是for的邏輯...) : 請其他版友分享更好的寫法!! : 1. cross validation: : 1.a 還是用到folds : sapply(1:5,function(i){ : testIndexes <- which(folds==i,arr.ind=T) : # 做你想做的事情 : # ex: 找測試集的最大值跟訓練集的最小值 : max_intest <- max(dataset[testIndexes,]) : min_intrain <- min(dataset[-testIndexes,]) : #回傳結果 : c(max_intest,min_intrain) : }) : 其實這個跟for的寫法根本換湯不換藥XD : 1.b 使用split (不要用cut跟folds) : 原po原本的方法是先用sample()抽樣打亂原始data的順序後再用cut()指定組別 : 提供sapply + split的做法: : sapply(split(dataset,1:5),function(x){ : test <- x # test dataset : train <- dataset[-as.numeric(row.names(x)),] # train dataset : # 做你想做的 : c(max(test),max(train)) : }) : 這個做法直接把dataset分成5份然後將該dataframe傳進sapply裡 : 不過須注意這作法取樣的順序跟cut不一樣 : cut是111..222...333...444..555(各20次) : split是12345...12345...12345...(共20次) : 不過因為一開始已經用sample打亂過順序了,所以個人覺得後面cut或split應該沒差 : (有錯請指正>"<) library(pipeR) library(data.table) N <- 100000L x <- runif(N) * 10 y <- x+rnorm(N) * 0.1 num_folds <- 10L split_idx <- seq_len(N) %>>% cut(breaks=num_folds, labels = FALSE) %>>% sample dataset <- data.table(x, y, split_idx, key = "split_idx") library(microbenchmark) microbenchmark(apply_func = { models <- seq_len(num_folds)%>>% lapply( function(i){ lm(y ~ x, dataset[split_idx != i]) }) mse_folds <- seq_len(num_folds) %>>% sapply(function(i){ mean((predict(models[[i]], dataset[split_idx == i]) - dataset[split_idx == i]$y)^2) }) }, for_loop = { models <- vector("list", num_folds) mse_folds <- vector("numeric", num_folds) for (i in seq_len(num_folds)) { models[[i]] <- lm(y ~ x, dataset[split_idx != i]) mse_folds[i] <- mean((predict(models[[i]], dataset[split_idx == i]) - dataset[split_idx == i]$y)^2) } }, times = 20L ) # Unit: milliseconds # expr min lq mean median uq max neval # apply_func 192.4187 199.8315 236.0988 209.2901 284.0653 365.0350 20 # for_loop 198.8673 206.2947 230.8822 210.7969 260.0005 301.9913 20 基本上沒差多少,開心用什麼就用什麼,重點還是forloop前的變數要allocate apply寫法有很多種,有人是不存model,那就不用拆兩段 有人直接一次return list(model, mse),這樣也不用拆兩段 我是覺得apply或是for-loop看coder開心就好XD 請參考 https://www.ptt.cc/man/R_Language/D5C7/M.1437921117.A.AC4.html : 2. 偷偷問的小問題 : x <- c(2:3) : y <- c(4:8) : sapply(x,function(i){ : i*y : }) : 其實我後來很常用 : sapply(x,function(){ : .... : }) 可以用microbenchmark去看效能,我猜其實沒差 這個例子outer最快 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.163.170.73 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1585186274.A.9D9.html ※ 編輯: celestialgod (118.163.170.73 臺灣), 03/26/2020 09:34:53

03/26 13:36, 4年前 , 1F
謝謝大大!沒想到還真的被釣出來了(欸
03/26 13:36, 1F

03/26 13:36, 4年前 , 2F
可能我的使用情境來說都還不到效能瓶頸,所以以前不太需要
03/26 13:36, 2F

03/26 13:36, 4年前 , 3F
注意效能問題,但還是很感謝C大分享!
03/26 13:36, 3F
文章代碼(AID): #1UV0NYdP (R_Language)
文章代碼(AID): #1UV0NYdP (R_Language)