Re: [問題] 如何更有效率的整理data的問題?

看板R_Language作者 (天)時間7年前 (2017/01/31 17:42), 7年前編輯推噓5(507)
留言12則, 1人參與, 最新討論串3/3 (看更多)
※ 引述《phil5566 (5566)》之銘言: : [問題類型]: : 效能諮詢(我想讓R 跑更快) : [軟體熟悉度]: : 新手(沒寫過程式,R 是我的第一次) : [問題敘述]: : 小弟自己產生一組data叫做"T"的矩陣, : 想把其中"T"的第5行(T[,5])和第6行(T[,6])的數據, : 挑出來整理成一個120X3的矩陣,假設叫"G", : T[,5]的數值有10,16,22,28,34,40,6個可能, : T[,6]的數值有0.5,1.5,2.5,.........,19.5和inf的可能, : 整理方法: : G的第一行(G[,1]):放0.5,1.5,....,19.5(20個數,6個循環,共120個) : G的第二行(G[,2]):放的東西比較麻煩,即 : T[,5]=10的情況下,對應到T[,6]那些0.5,1.5,.....,19.5,inf的數值 : 計算他們的累積比率,假設T[,5]=10,有100筆data, : T[,5]=10且T[,6]<=0.5(或者T[,6]<=1)有22筆, : 則它算出的累積比率為22/100=0.22,依此類推..., : 算到T[,5]=10且T[,6]<=19.5(或者T[,6]<=20)的累積比率 : 共20個數字放到G[1:20,2],重複以上模式處理T[,5]=16,22,28,34,40的情形 : 分別放到G[21:40,2],G[61:80,2],.....,G[101:120,2] : G的第三行(G[,3]):G[1:20,3]放10,G[21:40,3]放16,......G[101:120,3]放40 : ________________________________________________________________________ : 小弟之前是用table函數處理, : 直接table(T[,5],T[,6])得到分類結果 : 再分別計算累積比率,沒用到廻圈, : 但考慮到"假設T[,6]可能沒有出現5.5的情況", : table函數分類後就不會有5.5的這個分類, : 所以小弟又重新寫,用兩個廻圈來整理data, : 第一個廻圈是在處理G[,1]和G[,3],第二個廻圈在處理G[,2] : 以下附上code範例, : 想請教版上各位高手,大大有沒有更漂亮,快速的處理方法, : 指教了,謝謝~ : [程式範例]: : http://pastebin.com/bw0C2YNJ : [環境敘述]: : R x64 3.3.1 : [關鍵字]: : data整理 # generage T[,5]跟T[,6] targetMat <- cbind(sample(c(10,16,22,28,34,40), 2e4, TRUE), sample(c(seq(0.5,19.5,by = 1), Inf), 2e4, TRUE)) # 取unique的T[,5] g1 <- unique(targetMat[ , 1]) # 取T[,6] min ~ max(除去Inf),間隔1的序列,共20個 g2 <- seq(min(targetMat[ , 2]), max(targetMat[is.finite(targetMat[,2]), 2]), by = 1) # 展開g1跟g2,並加一行轉成矩陣 outputDF <- expand.grid(g1, g2) outputMat <- as.matrix(cbind(outputDF[order(outputDF$Var1, outputDF$Var2), ], 0)) # 用tapply計算每一個g1, g2對應的次數,第一個input隨意放即可,沒用到,我這裡放1 resMat <- tapply(rep(1, nrow(targetMat)), list(targetMat[,1], targetMat[, 2]), length) # 用cumsum算出累積次數,再用sweep算累積比率 # 最後再把矩陣拉直,變成outputMat的第三行 outputMat[ , 3] <- as.vector(sweep(apply(resMat[ , 1:20], 1, cumsum), 2, rowSums(resMat), `/`)) 最後一行可能要花時間消化一下,先從 apply(resMat[ , 1:20], 1, cumsum) 看起 然後去看sweep用法 看一下 rowSums(resMat) 代表的意義 組合起來就是你要的累積比率 另外要注意我有先對outputMat排序,才能直接放進去 再寫的時候要注意順序錯了,塞進去的結果就會不對了 -- R資料整理套件系列文: magrittr #1LhSWhpH (R_Language) https://goo.gl/72l1m9 data.table #1LhW7Tvj (R_Language) https://goo.gl/PZa6Ue dplyr(上.下) #1LhpJCfB,#1Lhw8b-s (R_Language) https://goo.gl/I5xX9b tidyr #1Liqls1R (R_Language) https://goo.gl/i7yzAz pipeR #1NXESRm5 (R_Language) https://goo.gl/zRUISx -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 118.170.46.59 ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1485855748.A.626.html

01/31 22:21, , 1F
謝謝C大回答~這個方法蠻厲害的,完全沒用到廻圈
01/31 22:21, 1F

01/31 22:23, , 2F
但還是有幾點疑問?您說的outputMat排序是指
01/31 22:23, 2F

01/31 22:24, , 3F
order(outputDF$Var1, outputDF$Var2)吧?order(X,Y)排序
01/31 22:24, 3F

01/31 22:26, , 4F
原則是否先比X再比Y,比完後越小的放越前面?
01/31 22:26, 4F
對,相比X再比Y,預設是increasing or ascending排序

01/31 22:29, , 5F
最後一行我還可以理解,只是tapply那一行就看不太懂?
01/31 22:29, 5F

01/31 22:30, , 6F
google"tapply"的用法還是有看沒有懂,能否麻煩C大解說一
01/31 22:30, 6F
tapply(x, y, fun): x是目標向量 y可以是向量或是list,向量長度要和x長度相同 若是list,每個元素的長度都要和x長度相同 fun是每一組要做的動作 舉例: tapply(1:6, rep(1:2, 3), mean) x y 1 1 2 2 3 1 就是y=1的對應的x取mean跟 1 2 (這個是group) 4 2 y=2的對應的y取mean => 3 4 (這個是value) 5 1 6 2 如果第二個是list tapply(1:6, list(rep(1:2,3), rep(1:3, each=2)), mean) x y1 y2 1 1 1 2 2 1 3 1 2 4 2 2 5 1 3 6 2 3 這樣就是 y1=1, y2=1的一組,y1=2, y2=1的一組, ... 分別取mean 這些其實在?tapply都可以找到,不需要google 我覺得看R程式範例去學習也是很重要的,要自己想辦法學習阿~~ 我的程式碼應該就簡單懂了,根據g1跟g2的分組計算每組的length

01/31 22:34, , 7F
下?最後就是假設產生sample的那個步驟如果只有產生10個
01/31 22:34, 7F

01/31 22:35, , 8F
那您做g2那個動作,取min還會取到0.5嗎?謝謝
01/31 22:35, 8F

01/31 22:38, , 9F
可能是我沒說清楚,我指的是不論今天sample產生出來是什
01/31 22:38, 9F

01/31 22:40, , 10F
都一定要有0.5,1.5,......,19.5這20個數的存在
01/31 22:40, 10F
對不起,我考慮的不夠周到,那你只能寫死了 g2 <- seq(0.5, 19.5, by = 1)

02/01 01:13, , 11F
讚讚讚~
02/01 01:13, 11F
最後順便回答你前一篇的問題 benchmark是評比的意思 你可以把程式分段去看執行時間 或是 直接使用profvis這個套件 可以比較容易抓出程式瓶頸的部分 再根據瓶頸部份去改善 柏拉圖法則:80%的速度瓶頸來自20%的程式碼 ※ 編輯: celestialgod (118.170.46.59), 02/01/2017 02:05:39

02/01 18:34, , 12F
馬上來試試
02/01 18:34, 12F
文章代碼(AID): #1Oa5m4Oc (R_Language)
文章代碼(AID): #1Oa5m4Oc (R_Language)