R 减去列对

R 减去列对,r,data.table,lapply,R,Data.table,Lapply,我有一个包含成对列的数据表: 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)) n<-2 cols <- paste0(rep(letters[1:2]

我有一个包含成对列的数据表:

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))
n<-2
cols <- paste0(rep(letters[1:2], n),rep(1:n,each=2))
"a1" "b1" "a2" "b2"
现在我想定义列的子集:

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))
n<-2
cols <- paste0(rep(letters[1:2], n),rep(1:n,each=2))
"a1" "b1" "a2" "b2"
我的目标与上一篇文章类似: , 因此,我尝试了以下方法:

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][]

myNames
.SD
也是一个
数据表。您必须使用
[[
来子集列(或使用
[,j,with=FALSE]
)。因此:
函数(x)(.SD[[2*(x-1)+1]-.SD[[2*(x-1)+2]]
将适用于您的情况。当您使用单个
[
,它实际上是从
.SD
中子集一行而不是一列(就像一个普通的
数据表发生的情况一样。

.SD
也是一个
数据表。
。你必须使用
[
来子集一列(或者使用
[,j,with=FALSE]
)。因此:
函数(x)(.SD[[2*(x-1)+1]-.SD[[2*(x-1)+2]]
将适用于你的情况。当你使用单个
[
,它实际上是将
.SD
中的一行而不是一列子集(就像正常的
数据.table
所发生的情况一样)。

如果列的顺序不同,访问列的算法看起来相当复杂,而且很脆弱

通过将数据从宽型改为长型,可以简化计算。长型数据是同时熔化两个测量柱的结果

cols <- c("a", "b")
melt(dt, measure.vars = patterns(cols), value.name = cols)]
现在,只需要计算列
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"]

访问列的算法看起来相当复杂,如果列的顺序不同,那么它就很脆弱

通过将数据从宽型改为长型,可以简化计算。长型数据是同时熔化两个测量柱的结果

cols <- c("a", "b")
melt(dt, measure.vars = patterns(cols), value.name = cols)]
现在,只需要计算列
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"]

很好!谢谢@mt1022,这正是我要找的。@mt1022:把你的评论升级为答案怎么样?显然,这对我来说比你更有用,但也可能对其他人更有用?无论如何,谢谢你的解释!请附加
[]
以打印结果,即
dt[,(myNames):=lapply(1:(ncol(.SD)/2),function(x)(.SD[2*(x-1)+1]-.SD[2*(x-1)+2]),.SDcols=cols][
Nice!谢谢@mt1022这就是我要找的。@mt1022:把你的评论推广到一个答案怎么样?显然对我来说比对你更有帮助,但也可能对其他人有帮助?无论如何,谢谢你的解释!请附加
[]
打印结果,即,
dt[,(myNames):=lappy(1:(ncol(.SD)/2),函数(x)(.SD[2*(x-1)+1]-.SD[2*(x-1)+2]),.SDcols=cols][]