推 phil5566: 謝謝clansoda大的回答,但是我用你的code跑過一遍之後發 01/31 16:02
→ phil5566: 現如果一開始產生data時沒有出現1.5,分類一樣不會出現 01/31 16:05
→ phil5566: 1.5,即產生出來的矩陣列數是小於120的矩陣 01/31 16:06
→ celestialgod: 因為他沒有看完你的文章XDD data.table做一樣是 01/31 16:07
→ celestialgod: 兩兩unique做 01/31 16:07
→ phil5566: 不過再請教一下,您的code裡有一行是 01/31 16:15
→ phil5566: dat[, .(Counting = .N), .(x, y)][order(x, y)] 01/31 16:16
→ phil5566: dat是一個矩陣,為何dat[,,]裡會有兩個"," 01/31 16:18
→ phil5566: ?".N"和".(x, y)"代表什麼意思? 01/31 16:24
→ phil5566: `:=`和:=又是什麼意思?謝謝 01/31 16:28
→ celestialgod: dat是data.table不是矩陣 01/31 16:33
→ celestialgod: :=跟 `:=`基本是相同,一個是函數form,另一個是 01/31 16:33
→ celestialgod: operator 01/31 16:33
→ celestialgod: :=是operator, `:=`是函數 01/31 16:34
→ celestialgod: .N是計算個數, .(x,y)是他少寫了by = .(x,y) 01/31 16:34
→ celestialgod: by是data.table拿來做grouping的一個input 01/31 16:34
→ celestialgod: 我覺得p大還是專心在matrix上的操作就好 01/31 16:34
推 phil5566: 受教了~謝謝 01/31 17:12
→ clansoda: 我有看完 不過我真心看不太懂 覺得要用範例比較好 01/31 20:45
> -------------------------------------------------------------------------- <
作者: celestialgod (天) 看板: R_Language
標題: Re: [問題] 如何更有效率的整理data的問題?
時間: Tue Jan 31 17:42:25 2017
※ 引述《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
推 phil5566: 謝謝C大回答~這個方法蠻厲害的,完全沒用到廻圈 01/31 22:21
→ phil5566: 但還是有幾點疑問?您說的outputMat排序是指 01/31 22:23
→ phil5566: order(outputDF$Var1, outputDF$Var2)吧?order(X,Y)排序 01/31 22:24
→ phil5566: 原則是否先比X再比Y,比完後越小的放越前面? 01/31 22:26
對,相比X再比Y,預設是increasing or ascending排序
推 phil5566: 最後一行我還可以理解,只是tapply那一行就看不太懂? 01/31 22:29
→ phil5566: google"tapply"的用法還是有看沒有懂,能否麻煩C大解說一 01/31 22:30
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
推 phil5566: 下?最後就是假設產生sample的那個步驟如果只有產生10個 01/31 22:34
→ phil5566: 那您做g2那個動作,取min還會取到0.5嗎?謝謝 01/31 22:35
→ phil5566: 可能是我沒說清楚,我指的是不論今天sample產生出來是什 01/31 22:38
→ phil5566: 都一定要有0.5,1.5,......,19.5這20個數的存在 01/31 22:40
對不起,我考慮的不夠周到,那你只能寫死了
g2 <- seq(0.5, 19.5, by = 1)
推 phil5566: 讚讚讚~ 02/01 01:13
最後順便回答你前一篇的問題
benchmark是評比的意思
你可以把程式分段去看執行時間
或是 直接使用profvis這個套件
可以比較容易抓出程式瓶頸的部分
再根據瓶頸部份去改善
柏拉圖法則:80%的速度瓶頸來自20%的程式碼
※ 編輯: celestialgod (118.170.46.59), 02/01/2017 02:05:39
推 phil5566: 馬上來試試 02/01 18:34