我有一对包含列的数据表:
set.seed(1)
dt <- data.table(a1 = round(runif(3),1), a2 = round(runif(3),1), a3 =round(runif(3),1),
b1 = round(runif(3),1), b2 = round(runif(3),1), b3 =round(runif(3),1))
它看起来像这样:
a1 a2 a3 b1 b2 b3
0.3 0.9 0.9 0.1 0.7 0.5
0.4 0.2 0.7 0.2 0.4 0.7
0.6 0.9 0.6 0.2 0.8 1.0
现在我想定义一个列的子集:
n<-2
cols <- paste0(rep(letters[1:2], n),rep(1:n,each=2))
"a1" "b1" "a2" "b2"
并为每对添加一个新列,区别为:
dt[,.(desired_ab1=c(0.2,0.2,0.4),desired_ab2=c(0.2,-0.2,0.1))]
desired_ab1 desired_ab2
0.2 0.2
0.2 -0.2
0.4 0.1
我的目标与之前的帖子类似: Sum pairs of columns by group, 所以我尝试了以下内容:
myNames <- paste0("ab_", seq(n))
dt[, (myNames):=lapply(1:(ncol(.SD)/2),
function(x) (.SD[2*(x-1)+1]-.SD[2*(x-1)+2])), .SDcols=cols][]
我不知道会发生什么。有人可以给我一个暗示失败的提示吗?
答案 0 :(得分:2)
.SD
也是data.table
。您必须使用[[
对列进行子集化(或使用[, j, with = FALSE]
)。所以这个:function(x) (.SD[[2*(x-1)+1]]-.SD[[2*(x-1)+2]])
将适合你的情况。当您使用单个[
时,它实际上是对.SD
中的行而不是列进行分类(就像普通data.table
所发生的那样)。
答案 1 :(得分:1)
访问列的算法看起来相当复杂,如果列的排序方式不同,则会很脆弱。
通过从宽到长形式重新整形数据,可以简化计算。长形式的数据是同时熔化两个测量柱的结果
cols <- c("a", "b")
melt(dt, measure.vars = patterns(cols), value.name = cols)]
variable a b 1: 1 0.3 0.1 2: 1 0.4 0.2 3: 1 0.6 0.2 4: 2 0.9 0.7 5: 2 0.2 0.4 6: 2 0.9 0.8 7: 3 0.9 0.5 8: 3 0.7 0.7 9: 3 0.6 1.0
现在,只需要计算列a
和b
之间的差异。最后,结果可以再次变换为宽形式(在过滤所需的对之后。
如果将所有部件组合在一起,则变为
# reshape from wide to long format with two measure variables
melt(dt, measure.vars = patterns(cols), value.name = cols)[
# calculate differences
, ab := a - b][
# select pairs of interest
variable %in% 1:2,
# reshape from long to wide format
dcast(.SD, rowid(variable) ~ paste0("ab", variable), value.var = "ab")][
# drop row id
, -"variable"]
ab1 ab2 1: 0.2 0.2 2: 0.2 -0.2 3: 0.4 0.1