2014-01-22 64 views
4

假設我想要逐行計算幾列的範圍的大小。對data.table的明智行操作

set.seed(1) 
dat <- data.frame(x=sample(1:1000,1000), 
        y=sample(1:1000,1000), 
        z=sample(1:1000,1000)) 

使用data.frame(),我會做這樣的事情:

dat$diff_range <- apply(dat,1,function(x) diff(range(x))) 

要說得簡單些,我在尋找這個操作,在每一行:

diff(range(dat[1,]) # for i 1:nrow(dat) 

如果我這樣做對整個表,這將是這樣的:

setDT(dat)[,diff_range := apply(dat,1,function(x) diff(range(x)))] 

但是,我將如何做只有命名(或編號)行?

+0

這個問題聽起來像所有你想要做的是數據框或數據表的子集,但基於你的個人資料,你知道如何做到這一點。你究竟想在這裏實現什麼? – JeremyS

+0

我認爲我的印象是,我可以在'apply()'表達式中使用表示法,類似於如何使用data.table重新引用列。這,我做了我所期望的:'dt [,diff_range:= apply(dt [,1:2,with = FALSE] ...'但我認爲有一些魔法可以做到:'apply(1: 2,...)''我想我在這裏回答了我自己的問題 –

+0

噢,是的,你可以,但不能用數據表這種方式,因爲它會改變dt而不是複製我用一種方式添加了一個答案最常見的是'%in%' – JeremyS

回答

2

pmax and pmin以向量化的方式找到跨列的最小值和最大值,這比分別對每一行進行分割和處理要好得多。它也很簡潔:

dat[, r := do.call(pmax,.SD) - do.call(pmin,.SD)] 


     x y z r 
    1: 266 531 872 606 
    2: 372 685 967 595 
    3: 572 383 866 483 
    4: 906 953 437 516 
    5: 201 118 192 83 
    ---     
996: 768 945 292 653 
997: 61 231 965 904 
998: 771 145 18 753 
999: 841 148 839 693 
1000: 857 252 218 639 
1

您可以在函數之前/期間通過子集來完成。如果你只想例如每隔一行

dat_Diffs <- apply(dat[seq(2,1000,by=2),],1,function(x) diff(range(x))) 

或爲rownames 1:10(因爲沒有指定他們的名字,他們只是數字計數)

dat_Diffs <- apply(dat[rownames(dat) %in% 1:10,],1,function(x) diff(range(x))) 

但是,爲什麼不只是計算每然後行子集?

4

如何:

D[,list(I=.I,x,y,z)][,diff(range(x,y,z)),by=I][c(1:4,15:18)] 
# I V1 
#1: 1 971 
#2: 2 877 
#3: 3 988 
#4: 4 241 
#5: 15 622 
#6: 16 684 
#7: 17 971 
#8: 18 835 

#actually this will be faster 
D[c(1:4,15:18),list(I=.I,x,y,z)][,diff(range(x,y,z)),by=I] 

使用。我給你一個指標與by=參數來調用,然後你可以運行在每一行的功能。第二個調用預先過濾任何行號列表,或者如果您的真實表格看起來不同,您可以添加一個鍵和過濾器。

+1

但這個解決方案只有在你明確指定每一列的名稱時纔有效,如果有太多或者你不知道它就不會工作 – skan