在data.table

时间:2016-12-07 17:18:51

标签: r data.table colon-equals

我经常发现自己在同一个数据表上使用:=进行了一系列链式计算。例如,像这样的东西

test = data.table(1:10, 1:10, 1:10, 1:10)

test[, V1 := V1^2]
test[, V2 := V1*V2]
test[, V3 := V2/V3]
test[, V4 := sqrt(V3)]
test[, new := letters[V4]]

必须在每一行上写test[, ...] 1)需要更长的时间来打字(这不是一个很大的问题,我可以解决这个问题)。但是,更重要的是,还会在视觉上分散计算的流程和内容。我更愿意写点像

test[, {
  V1 := V1^2
  V2 := V1*V2
  V3 := V2/V3
  V4 := sqrt(V3)
  new := letters[V4]
}]

但这会引发You have wrapped := with {} which is ok but then := must be the only thing inside {}的错误。

我知道我可以写

within(test, {
  V1 = V1^2
  V2 = V1*V2
  V3 = V2/V3
  V4 = sqrt(V3)
  new = letters[V4]
  })

但这会失去使用:=

的效率

我尝试编写一个提供此功能的功能

with.dt = function(dt, expressions){
  e = strsplit(expressions,'\n')
  for (i in 1:length(e)){    
    dt[, eval(parse(text = e[i]))]
  }
  dt
  }

with.dt(test, "
  V1 := V1^2;
  V2 := V1*V2;
  V3 := V2/V3;
  V4 := sqrt(V3);
  new := letters[V4];
  ")

但这不会改变data.table的内容

是否有任何语法允许within版本的整洁外观,同时保留:=的引用属性?

2 个答案:

答案 0 :(得分:2)

有几种不同的方法可以做到这一点。

此处使用的原始测试矩阵:

   v1 v2
1:  1  3
2:  2  4

首先,我们可以这样做:

test[,`:=`(v1 = v1^2,
          v2 = v1*v2)

输出:

v1 v2
 1  3
 4  8

或者,如果我们想要按顺序完成,我们可以使用Frank的黑客。

test[, `:=`(v1 = v1 <- v1^2, v2 = v2 * v1)]

输出:

v1 v2
 1  3
 4 16  

或者,同样我们可以运行:

test[,c("v1","v2") := list(v1^2,v1^2*v2)]

输出:

v1 v2
 1  3
 4 16

答案 1 :(得分:1)

我们可以使用一个带有表达式列表的函数:

 context.Entry(entity).State = EntityState.Unchanged; 

// Do some change... 
entity.value=5; 

context.SaveChanges();