我有一组如下所示的因素:
v.list <- c('AM','EM','SMH')
我想基于数据集中的先前列计算数据集中的新列,这些列都是由这些标识符之一无意识地定义的。以下是一些示例数据:
height.pre.AM <- rnorm(10)
height.pre.EM <- rnorm(10)
height.pre.SMH <- rnorm(10)
height.post.AM <- rnorm(10)
height.post.EM <- rnorm(10)
height.post.SMH <- rnorm(10)
d<- data.table(height.pre.AM,height.pre.EM,height.pre.SMH,height.post.AM,height.post.EM,height.post.SMH)
然后,我想通过列表中的每个标识符计算3个新向量,前向量和后向量之间的高度变化。我可以用3行看起来像这样:
d[,delta_EM := height.post.EM - height.pre.EM ]
d[,delta_AM := height.post.AM - height.pre.AM ]
d[,delta_SMH := height.post.SMH - height.pre.SMH]
如何使用单行执行此操作,存储为v.list
的矢量位于上方?
我尝试了一个构造为:
的for循环for(i in 1: length(v.list)){
v <- (noquote(paste(v.list[i])))
pre <- paste("d[,delta_",v,":= height.post.",v," - height.pre.",v,"]",sep="")
cat(noquote(pre), sep="\n")
}
然而,这只是打印线条,而不是执行它们。
答案 0 :(得分:4)
另一种可能性是首先将数据转换为长格式。使用 data.table 中增强的melt
函数,您可以按模式使用多个度量,从而创建多个值列(在本例中为 pre 和帖子值列):
melt(d, measure.vars = patterns("pre","post"),
value.name = c("height.pre","height.post"))[, variable := v.list[variable]
][, delta_height := height.post - height.pre][]
给出:
variable height.pre height.post delta_height
1: AM 1.51181796 0.20232291 -1.3094951
2: AM 0.65902517 0.51772371 -0.1413015
3: AM 1.12202807 1.67814321 0.5561151
4: AM -0.78464137 0.38524481 1.1698862
5: AM -0.42569229 -1.28188722 -0.8561949
6: AM 0.39299759 -0.58215074 -0.9751483
7: AM 0.03675713 1.77411869 1.7373616
8: AM -1.03208366 -0.21067198 0.8214117
9: AM -1.26486147 -0.35210691 0.9127546
10: AM -0.22696529 0.58517233 0.8121376
11: EM 0.74558930 1.01368470 0.2680954
12: EM 0.33281918 -0.02256943 -0.3553886
.....
答案 1 :(得分:3)
可能有一种更好的方法,但是我提出的方法似乎有效。您可以在数据表中使用lapply()
和get()
。
d[, paste0("delta_", v.list) := lapply(v.list, function(x) {
s <- sort(grep(x, names(d), fixed = TRUE, value = TRUE))
get(s[1]) - get(s[2])
})]
或者,您可以解析并评估某些表达式。
cols <- lapply(v.list, function(x) {
g <- grep(paste0("p(ost|re)\\.", x), names(d), value = TRUE)
eval(parse(text = paste(g, collapse = "-")), envir = d)
})
d[, paste0("delta_", v.list) := cols]
答案 2 :(得分:3)
你走了:
for (v in v.list)
d[, paste0('delta_', v) := get(paste0('height.post.', v)) -
get(paste0('height.pre.', v))]
答案 3 :(得分:2)
您可能需要考虑使用dplyr
和tidyr
,因为这些软件包非常适合这些操作并生成可读且整洁的工作流代码。
Vectorize(require)(package = c("dplyr", "tidyr"),
character.only = TRUE)
dComplete <- d %>%
gather(key = indPre, value = valPre, contains("pre")) %>%
gather(key = indPost, value = valPost, contains("post")) %>%
mutate(diff = valPost - valPre)
我set.seed(1)
表示可重复性:
set.seed1(1)
height.pre.AM <- rnorm(10)
height.pre.EM <- rnorm(10)
height.pre.SMH <- rnorm(10)
height.post.AM <- rnorm(10)
height.post.EM <- rnorm(10)
height.post.SMH <- rnorm(10)
d<- data.frame(height.pre.AM, height.pre.EM, height.pre.SMH,
height.post.AM,height.post.EM,height.post.SMH)
> head(dComplete)
indPre valPre indPost valPost diff
1 height.pre.AM 0.2426995 height.post.AM -1.0155539 -1.2582534
2 height.pre.AM -0.7978763 height.post.AM 0.7602261 1.5581023
3 height.pre.AM -0.2440429 height.post.AM -1.7585200 -1.5144772
4 height.pre.AM -1.4228071 height.post.AM 0.7663306 2.1891377
5 height.pre.AM 1.6237066 height.post.AM 1.0676800 -0.5560266
6 height.pre.AM 0.3561212 height.post.AM -0.4366372 -0.7927584
如果需要,您可以稍后将spread
您的值放入一列;取决于你想如何使用这些数据。
答案 4 :(得分:1)
这是一种方式:
FocusManager
如果你愿意,你可以把它塞进一行,但那不太可读。