给定data.table和指示多个目标列的向量:替换目标列的最有效方法是什么?第1行和第r行的值是否为(r-1)加1?
的值整个操作应该由一个名为id1的键重复。
原始data.table和目标列看起来像这样
library(data.table)
DT <- data.table(id1=c(1,1,1,2,2,2), id2=c(1,2,3,1,2,3), c1=c(0,1,0,2,1,2), c2=c(0,0,1,1,2,3), c3=c(1,2,2,1,1,1))
setkey(DT,id1,id2)
cnames <- c("c1","c2","c3")
DT
# id1 id2 c1 c2 c3
# 1: 1 1 0 0 1
# 2: 1 2 1 0 2
# 3: 1 3 0 1 2
# 4: 2 1 2 1 1
# 5: 2 2 1 2 1
# 6: 2 3 2 3 1
这是理想的结果
# id1 id2 c1 c2 c3
# 1: 1 1 1 1 1 #substituted by 1
# 2: 1 2 1 1 2 # previous row + 1
# 3: 1 3 2 1 3 # "
# 4: 2 1 1 1 1 # substituted by 1
# 5: 2 2 3 2 2 # previous row + 1
# 6: 2 2 2 3 2 # "
我知道像DT[,"c1" := c(1,c1[.I-1]+1), by=id1]
这样的东西可能有用,但这会带来两个挑战:首先,c1[.I-1]
的第一个值没有定义。第二,使用此代码的替换将针对一个clumn执行(此处:&#34; c1&#34;),而我需要对多个列执行替换,在向量&#34; cnames&#34中指示;
谢谢!亚娜
答案 0 :(得分:3)
最简单的方法是首先为每个组设置第一行到所有0。然后,为每列添加1。这相当于您希望做的事情。以下是我的表现:
setkey(DT, id1)
DT[J(unique(id1)), c(cnames) := list(0L), mult="first"]
DT[, c(cnames) := .SD+1L, .SDcols=cnames]
# id1 id2 c1 c2 c3
# 1: 1 1 1 1 1
# 2: 1 2 2 1 3
# 3: 1 3 1 2 3
# 4: 2 1 1 1 1
# 5: 2 2 2 3 2
# 6: 2 3 3 4 2
根据OP的评论并编辑问题:
您可以按如下方式完成此操作:首先将行换1列,同时将第一列替换为0&#39; s,然后将1添加到所有列。
DT[, c(cnames) := lapply(.SD, function(x)
c(0L, head(x, -1L))), by=id1, .SDcols=cnames]
DT[, c(cnames) := .SD+1L, .SDcols=cnames]
> DT
# id1 id2 c1 c2 c3
# 1: 1 1 1 1 1
# 2: 1 2 1 1 2
# 3: 1 3 2 1 3
# 4: 2 1 1 1 1
# 5: 2 2 3 2 2
# 6: 2 3 2 3 2
通过查看评论中的问题的另一种变体:
首先将整个数据移动1行,不进行分组,然后将其加1。然后,将每个组的第一行设置为所有1。
setkey(DT, id1)
DT[2:nrow(DT), c(cnames) := head(DT[, cnames, with=FALSE], -1L) + 1L]
DT[J(unique(id1)), c(cnames) := list(1L), mult="first"]