Re: [問題] 創造dummy variable

看板R_Language作者 (天)時間9年前 (2016/12/27 18:29), 9年前編輯推噓1(105)
留言6則, 3人參與, 最新討論串6/6 (看更多)
※ 引述《clansoda (小笨)》之銘言: : 我自己來回我自己的問題 我採用的解法是andrew大的解法 : C版的解法看起來應該是最快的 但是小弟無法理解在幹嘛 : 所以選擇了一個看起來比我的快很多又能理解的方法 : kk <- Sys.time() : klist <- lapply(1 : NROW(target), function(k){ : target[k,] %>% as.numeric %>% .[!is.na(.)] : }) : test <- lapply(klist, function(k) { : m <- logical(20) : m[k] <- TRUE : return(m) : }) %>% do.call(rbind, .) : Sys.time() - kk : Time difference of 53.88025 secs : 我稍微修正過andrew大在提取每個row裡的值成為list的這一段碼 : 這樣可以將速度從180幾秒提到50秒左右 : 以我目前這個50萬row的資料等級來說這個速度我個人可以接受了 : 等到C大提點他的程式碼的邏輯以後可能會再修改我的寫法 : 目前先到這樣 感謝各位先進的提供的作法 受益良多 結果應該是一樣的,程式: library(data.table) target <- fread(' a b c 2 5 NA 1 NA NA 1 2 3 3 NA NA 2 4 NA 1 4 5 ') mat <- as.matrix(target) library(magrittr) system.time({ klist <- lapply(1 : NROW(target), function(k){ target[k,] %>% as.numeric %>% .[!is.na(.)] }) test <- lapply(klist, function(k) { m <- logical(5) m[k] <- TRUE return(m) }) %>% do.call(rbind, .) }) system.time({ idx <- nrow(mat) * (mat - 1L) idx <- idx[which(!is.na(idx))] + which(!is.na(mat), arr.ind = TRUE)[, 1] out <- matrix(FALSE, nrow(mat), 5L) out[idx] <- TRUE dim(out) <- c(nrow(mat), 5L) }) all.equal(test, out) # TRUE 我程式有點偷懶,是因為假設level數跟input的coloumn數會一樣 我這裡解釋一下我的程式邏輯: 我們先看一下輸出的結果 [,1] [,2] [,3] [,4] [,5] [1,] FALSE TRUE FALSE FALSE TRUE [2,] TRUE FALSE FALSE FALSE FALSE [3,] TRUE TRUE TRUE FALSE FALSE [4,] FALSE FALSE TRUE FALSE FALSE [5,] FALSE TRUE FALSE TRUE FALSE [6,] TRUE FALSE FALSE TRUE TRUE 第一列是2, 5要為TRUE,對應到input的第一列 2, 5, NA 第二列是1是TRUE,對應到input的第一列 1, NA, NA 所以我只要有(1, 2), (1, 5), (2, 1), ... 的位置向量 就可以把TRUE位置都描述出來 而且(1, 2), (1, 5), ...這些位置也可以用一個index表示 (這裡計算是根據coloumn-major的矩陣,row-major則會有一點不同) 矩陣中 (1, 2)位置其實可以用 1 + nrow(matrix) * (2 - 1) = 7 (這列有6個row) (1, 5)位置可以用 1 + nrow(matrix) * (5 - 1) = 25 (2, 1)位置可以用 2 + nrow(matrix) * (1 - 1) = 2 ... 來表示 所以我們可以得到一個通式: (i, j) => i + nrow(matrix) * (j - 1) 換到我的程式上來看 這行 idx <- nrow(mat) * (mat - 1L) 是把後面那個部分算出來 可是因為mat裡面充滿了NA,所以要滿NA先移除掉就有了下一行的前半段: idx[which(!is.na(idx))] 那i要怎麼辦,就利用which + !is.na去把對應的列位置取出 於是我們就得到了TRUE位置的index: idx <- idx[which(!is.na(idx))] + which(!is.na(mat), arr.ind = TRUE)[, 1] 那最後我只要把output的矩陣弄出來: out <- matrix(FALSE, nrow(mat), 5L) # 這裡的5是指target中最大的數字,可以用max(mat[!is.na(mat)])取得 然後再把TRUE位置補上,改一下dim: out[idx] <- TRUE dim(out) <- c(nrow(mat), 5L) # 這個5同前面的5意思 如此一來就可以得到正確答案了 這個方法比較tricky一點,但是向量化的精神就在這裡 向量化的程式需要一點的數學 跟 邏輯推演,不是那麼直覺就寫得出來 但是它的performance會真的很好~~~~ -- 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.42.16 ※ 文章網址: https://www.ptt.cc/bbs/R_Language/M.1482834566.A.09D.html ※ 編輯: celestialgod (118.170.42.16), 12/27/2016 18:30:15

12/28 01:49, , 1F
推好心解釋。這算法有趣。
12/28 01:49, 1F

12/29 14:37, , 2F
感謝C大 我研究一下後看懂了 向量化至少快50倍
12/29 14:37, 2F

12/29 14:37, , 3F
我想請問為什麼我最初的那個方法那麼慢 是因為我每一次
12/29 14:37, 3F

12/29 14:38, , 4F
指定column數的時候 都會在複製一次整個data.table嗎
12/29 14:38, 4F

12/29 18:52, , 5F
因為data.table那樣改值很慢,要用set,另外這個用m
12/29 18:52, 5F

12/29 18:52, , 6F
atrix改值還會比這個快
12/29 18:52, 6F
文章代碼(AID): #1OOaA62T (R_Language)
文章代碼(AID): #1OOaA62T (R_Language)