有没有办法更改几列并保留所有其他列,而不是通过引用分配或使用副本?

时间:2017-07-11 06:53:42

标签: r data.table dplyr

考虑示例数据:

tmp_dt <- data.table(a = 1:3, b = 2:4, c = 3:5)
tmp_dt
#    a b c
# 1: 1 2 3
# 2: 2 3 4
# 3: 3 4 5

例如,取列b的否定值,并将此新数据表传递给计算,而不修改tmp_dt。我知道一种方法是copy(tmp_dt)[, b := -b][],它产生:

#    a  b c
# 1: 1 -2 3
# 2: 2 -3 4
# 3: 3 -4 5

但是,我不喜欢这个,因为当你希望首先对copy做一些复杂的事情时,我发现tmp_dt凌乱的左右括号,例如,copy(tmp_dt)[do complicated stuff][...] vs copy(tmp_dt[do complicated stuff])[...]

换句话说,我希望能够像dplyr链一样从左到右阅读操作顺序:tmp_dt %>% do complicated stuff %>% copy。在不保留列顺序的情况下执行此操作的一种方法是:

tmp_dt[, c(.(b = -b), .SD), .SDcols = -'b']
#     b a c
# 1: -2 1 3
# 2: -3 2 4
# 3: -4 3 5

有没有人知道更优雅的data.table方法可以做到或改进吗?

2 个答案:

答案 0 :(得分:1)

您可以使用

 tmp_dt[, .SD][, b := -b]

或简单地说,

 tmp_dt[, .(a, b = -b, c)]

答案 1 :(得分:0)

这似乎有效,并且比我在OP中的第一次尝试更不笨拙,而且保留了原始列排序:

tmp_dt[, copy(.SD)[, b := -b]][]

# a  b c
# 1: 1 -2 3
# 2: 2 -3 4
# 3: 3 -4 5

FAQ 4.5中解释了.SD的操作:

  

.SD被设计锁定。请参阅?data.table。如果您想在使用之前操作.SD或返回它,并且不希望使用:=修改DT,那么先复制一份(参见?copy),例如,