假设我想逐行计算几列的范围大小。
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 :(得分: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)
pmax
和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
答案 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)))
但为什么不计算每行然后再计算子集?