基于列名模式的多个成对差异
Multiple pairwise differences based on column name patterns
我有一个data.table
, dt:
dt
Id v1 v2 v3 x1 x2 x3
1 7 1 3 5 6 8
2 1 3 5 6 8 5
3 3 5 6 8 5 1
v1、v2、v3 和 x1、x2、x3 是数值变量
我想从 'v' 列中减去 'x' 列,即计算差异 v1 - x1
、v2 - x2
等。在我的真实数据中,我可能有100 个这样的变量对。
期望的输出:
dt
Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
1 7 1 3 5 6 8 -2 -4 -3
2 1 3 5 6 8 5 -5 -5 0
3 3 5 6 8 5 1 -3 0 5
我尝试了以下方法:
newnames <- paste0("diff", 1:3)
v <- paste0("v", 1:3)
x <- paste0("x", 1:3)
dt[ , c(newnames) := get(v) - get(x)]
但是,这会导致 3 个相同的列都包含差异 v1 - x1
。
我知道可能的解决方案类似于
dt[ , .(v1 - x1, v2 - x2, v3 - x3)]
但是,如果我必须输入 100 个不像 v1 和 x1 那样简单的名称,那么这是一个很长的代码,可能会有很多打字错误。
希望你能帮帮我。
可以根据列是否包含x
进行拆分,然后对结果数据表进行差分
new_cols <-
do.call('-', split.default(dt[,-1], grepl('x', names(dt)[-1])))
dt[, paste0('diff', seq_along(new_cols)) := new_cols]
dt
# Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1: 1 7 1 3 5 6 8 2 -5 -5
# 2: 2 1 3 5 6 8 5 -5 -5 0
# 3: 3 3 5 6 8 5 1 -5 0 5
或者使用与您可以执行的问题中的代码片段类似的逻辑
newnames <- paste0("diff",1:3)
v <- paste0("v",1:3)
x <- paste0("x",1:3)
dt[, (newnames) := Map('-', mget(v), mget(x))]
dt
# Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1: 1 7 1 3 5 6 8 2 -5 -5
# 2: 2 1 3 5 6 8 5 -5 -5 0
# 3: 3 3 5 6 8 5 1 -5 0 5
您可以在循环中使用 set
。
library(data.table)
DT <- fread('Id v1 v2 v3 x1 x2 x3
1 7 1 3 5 6 8
2 1 3 5 6 8 5
3 3 5 6 8 5 1')
for (i in 1:3) {
set(DT,j=paste0("Diff_",i),value = DT[[paste0("v",i)]]-DT[[paste0("x",i)]])
}
DT
#> Id v1 v2 v3 x1 x2 x3 Diff_1 Diff_2 Diff_3
#> 1: 1 7 1 3 5 6 8 2 -5 -5
#> 2: 2 1 3 5 6 8 5 -5 -5 0
#> 3: 3 3 5 6 8 5 1 -5 0 5
由 reprex package (v0.3.0)
于 2020-05-27 创建
您的数据看起来属于长格式,您之后的计算将变得微不足道:
# reshape
DT_long = melt(DT, id.vars='Id', measure.vars = patterns(v = '^v', x = '^x'))
DT_long
# Id variable v x
# 1: 1 1 7 5
# 2: 2 1 1 6
# 3: 3 1 3 8
# 4: 1 2 1 6
# 5: 2 2 3 8
# 6: 3 2 5 5
# 7: 1 3 3 8
# 8: 2 3 5 5
# 9: 3 3 6 1
现在很简单:
DT_long[ , diff := v - x][]
# Id variable v x diff
# 1: 1 1 7 5 2
# 2: 2 1 1 6 -5
# 3: 3 1 3 8 -5
# 4: 1 2 1 6 -5
# 5: 2 2 3 8 -5
# 6: 3 2 5 5 0
# 7: 1 3 3 8 -5
# 8: 2 3 5 5 0
# 9: 3 3 6 1 5
然后您可以使用 dcast
重新整形为宽,但通常值得考虑的是,将数据集保持在这种长格式是否对整个分析更好。
我有一个data.table
, dt:
dt
Id v1 v2 v3 x1 x2 x3
1 7 1 3 5 6 8
2 1 3 5 6 8 5
3 3 5 6 8 5 1
v1、v2、v3 和 x1、x2、x3 是数值变量
我想从 'v' 列中减去 'x' 列,即计算差异 v1 - x1
、v2 - x2
等。在我的真实数据中,我可能有100 个这样的变量对。
期望的输出:
dt
Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
1 7 1 3 5 6 8 -2 -4 -3
2 1 3 5 6 8 5 -5 -5 0
3 3 5 6 8 5 1 -3 0 5
我尝试了以下方法:
newnames <- paste0("diff", 1:3)
v <- paste0("v", 1:3)
x <- paste0("x", 1:3)
dt[ , c(newnames) := get(v) - get(x)]
但是,这会导致 3 个相同的列都包含差异 v1 - x1
。
我知道可能的解决方案类似于
dt[ , .(v1 - x1, v2 - x2, v3 - x3)]
但是,如果我必须输入 100 个不像 v1 和 x1 那样简单的名称,那么这是一个很长的代码,可能会有很多打字错误。
希望你能帮帮我。
可以根据列是否包含x
进行拆分,然后对结果数据表进行差分
new_cols <-
do.call('-', split.default(dt[,-1], grepl('x', names(dt)[-1])))
dt[, paste0('diff', seq_along(new_cols)) := new_cols]
dt
# Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1: 1 7 1 3 5 6 8 2 -5 -5
# 2: 2 1 3 5 6 8 5 -5 -5 0
# 3: 3 3 5 6 8 5 1 -5 0 5
或者使用与您可以执行的问题中的代码片段类似的逻辑
newnames <- paste0("diff",1:3)
v <- paste0("v",1:3)
x <- paste0("x",1:3)
dt[, (newnames) := Map('-', mget(v), mget(x))]
dt
# Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1: 1 7 1 3 5 6 8 2 -5 -5
# 2: 2 1 3 5 6 8 5 -5 -5 0
# 3: 3 3 5 6 8 5 1 -5 0 5
您可以在循环中使用 set
。
library(data.table)
DT <- fread('Id v1 v2 v3 x1 x2 x3
1 7 1 3 5 6 8
2 1 3 5 6 8 5
3 3 5 6 8 5 1')
for (i in 1:3) {
set(DT,j=paste0("Diff_",i),value = DT[[paste0("v",i)]]-DT[[paste0("x",i)]])
}
DT
#> Id v1 v2 v3 x1 x2 x3 Diff_1 Diff_2 Diff_3
#> 1: 1 7 1 3 5 6 8 2 -5 -5
#> 2: 2 1 3 5 6 8 5 -5 -5 0
#> 3: 3 3 5 6 8 5 1 -5 0 5
由 reprex package (v0.3.0)
于 2020-05-27 创建您的数据看起来属于长格式,您之后的计算将变得微不足道:
# reshape
DT_long = melt(DT, id.vars='Id', measure.vars = patterns(v = '^v', x = '^x'))
DT_long
# Id variable v x
# 1: 1 1 7 5
# 2: 2 1 1 6
# 3: 3 1 3 8
# 4: 1 2 1 6
# 5: 2 2 3 8
# 6: 3 2 5 5
# 7: 1 3 3 8
# 8: 2 3 5 5
# 9: 3 3 6 1
现在很简单:
DT_long[ , diff := v - x][]
# Id variable v x diff
# 1: 1 1 7 5 2
# 2: 2 1 1 6 -5
# 3: 3 1 3 8 -5
# 4: 1 2 1 6 -5
# 5: 2 2 3 8 -5
# 6: 3 2 5 5 0
# 7: 1 3 3 8 -5
# 8: 2 3 5 5 0
# 9: 3 3 6 1 5
然后您可以使用 dcast
重新整形为宽,但通常值得考虑的是,将数据集保持在这种长格式是否对整个分析更好。