[討論] for loop與*apply function請益

看板R_Language作者 (locka)時間9年前 (2015/05/22 03:29), 編輯推噓2(2017)
留言19則, 5人參與, 最新討論串1/4 (看更多)
各位大大晚安, 我有一份總共九個欄位約30萬筆的原始資料, 因為想要分成4組畫圖 所以第一個想到的事就是新增第十個欄位(稱作group), 然後根據某個欄位(假設為第八個欄位好了)的值分組, 並填入第十個欄位(group1~group4) 很笨的用for loop搭配if else寫,可是速度整個悲劇... 好讀程式碼請見: http://pastie.org/10200854 add.col.group <- function(data){ data$group <- 0 for(i in 1:nrow(data)){ if(data[i,8] < 0.25){data[i,10] <- "group1"} else if(data[i,8] < 0.5 & data[i,8] > 0.25){data[i,10] <- "group2" } else if(data[i,8] < 0.75 & data[i,8] > 0.5){data[i,10] <- "group3" } else {data[i,10] <- "group4" } } data } ## call function new.data <- add.col.group(data) 後來嘗試改成用sapply搭配自己寫的判斷函式 好讀程式碼請見: http://pastie.org/10200933 ## 判斷分組 assign.group <- function(value){ if(value < 0.25){return_value <- "group1"} else if(value < 0.5){return_value <- "group2" } else if(value < 0.75){return_value <- "group3" } else return_value <- "group4" return_value } ## 新增欄位並填入值 add.col.group <- function(data){ data$group <- 0 data$group <- sapply(data$avg, assign_group) ##avg即為第八個欄位的名稱 data } ## call function new_data <- add.col.group(data) 結果沒想到,速度竟然是爆發性的進展!!!(驚) (因為怕爆掉,先用2萬筆資料測試) 用for loop寫: user system elapsed 0.11 0.00 0.11 用sapply寫: user system elapsed 42.18 0.00 43.02 可是不知道這樣的寫法會不會很笨...還有更好的寫法嗎? 還是其實根本不應該用*apply寫? 還請各位高手大大指點一下,謝謝大家了! 後記: 原本是想要發文求指點sapply的寫法... 結果剛剛文章打到一半當掉的時候, 突然靈光乍現了! 雖然好像沒有很難, 可是能靠自己的力量想出來總是很開心的一件事啊>"< (儘管文章要重打很累XD) [環境敘述]: version.string R version 3.0.3 (2014-03-06) [關鍵字]: for loop, sapply -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 59.115.22.250 ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1432236554.A.019.html

05/22 09:06, , 1F
apply和for差不多吧,vectorize才會變快
05/22 09:06, 1F

05/22 09:34, , 2F
用cut+cbind
05/22 09:34, 2F

05/22 09:34, , 3F
或是用 nvec <- c(NA, length=nrow(da))
05/22 09:34, 3F

05/22 09:35, , 4F
nvec[da[, 8]<.25] <- "grp1"
05/22 09:35, 4F

05/22 09:35, , 5F
依此類推,最後再cbind
05/22 09:35, 5F

05/22 13:57, , 6F
Function內包function是主因
05/22 13:57, 6F

05/22 13:58, , 7F
這種寫法很不容易寫 效率又會爆炸性的變差 真的是事倍功半
05/22 13:58, 7F

05/22 14:30, , 8F
另外一個大問題
05/22 14:30, 8F

05/22 14:31, , 9F
我直接開一篇好了
05/22 14:31, 9F

05/22 22:33, , 10F
二個關鍵:用 cut(),以及不要多次改寫 data frame。
05/22 22:33, 10F

05/22 22:36, , 11F
用對方法的話,20萬筆應該按enter就馬上有結果不會卡。
05/22 22:36, 11F

05/23 00:25, , 12F
在此先謝謝obarisk,gsuper,andrew43等大大熱情的回應。我
05/23 00:25, 12F

05/23 00:25, , 13F
覺得andrew大講到一個點,就是我一直想要改寫data frame,
05/23 00:25, 13F

05/23 00:25, , 14F
因為對我來說總覺得這樣資料比較好懂不會亂(似乎腦袋好像
05/23 00:25, 14F

05/23 00:25, , 15F
還停留在用一般dbms的table在理解r的data frame…)待我測
05/23 00:25, 15F

05/23 00:25, , 16F
試後有心得再跟大家分享,先謝謝大家了!
05/23 00:25, 16F

05/23 01:08, , 17F
我的「改寫」的意思是不要頻繁地改變data frame
05/23 01:08, 17F

05/23 01:09, , 18F
因為這會算很慢,並不是指不要改變data frame喔
05/23 01:09, 18F

05/24 02:48, , 19F
看起來dplyr可以完美解決你的問題
05/24 02:48, 19F
文章代碼(AID): #1LNZ8A0P (R_Language)
文章代碼(AID): #1LNZ8A0P (R_Language)