对data.table进行行操作

时间:2014-01-22 05:49:13

标签: r 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)))]

但是,我如何仅针对命名(或编号)行进行此操作?

3 个答案:

答案 0 :(得分: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]

使用.I为您提供使用by=参数调用的索引,然后您可以在每一行上运行该函数。第二个调用按任何行号列表进行预过滤,或者如果您的真实表看起来不同,您可以添加一个键并对其进行过滤。

答案 1 :(得分:4)

pmaxpmin以向量化方式查找列的最小值和最大值,这比分别分别处理每一行要好得多。它也非常简洁:

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

答案 2 :(得分: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)))

但为什么不计算每行然后再计算子集?