以下是关于您的选择的一些想法,主要来自评论:
apply
沿着行
OP的方法使用apply(.,1,.)
对于按行操作,但不鼓励这样做,因为它不必要地将 data.table 强制转换为矩阵。lapply
/sapply
也不适合,因为它们被设计为分别在每个列上工作,而不是组合它们。
rowMeans
类似名称的函数也强制转换为矩阵。
按行分割
正如@Jaap所说,你可以使用by=1:nrow(dt)
对于任何行操作,但它可能会很慢。
高效创建新列
这个方法取自eddi如果您必须以宽格式保存数据,这可能是最有效的:
jwts = list(
q1_AVG = c(q1_exam1 = 1 , q1_exam2 = 1 , q1_final = 1)/3,
q2_WAVG = c(q1_exam1 = 1/4, q2_exam2 = 1/4, q2_final = 1/2)
)
for (newj in names(jwts)){
w = jwts[[newj]]
dt[, (newj) := Reduce("+", lapply(names(w), function(x) dt[[x]] * w[x]))]
}
这避免了对矩阵的强制并允许不同的加权规则(与rowMeans
).
Go long
正如 @alexis_laz 所建议的,您可能会通过不同的结构获得清晰度和效率,例如
# reshape
m = melt(dt, id.vars="id", value.name="score")[,
c("quarter","exam") := tstrsplit(variable, "_")][, variable := NULL]
# input your weighting rules
w = unique(m[,c("quarter","exam")])
w[quarter=="q1" , wt := 1/.N]
w[quarter=="q2" & exam=="final", wt := .5]
w[quarter=="q2" & exam!="final", wt := (1-.5)/.N]
# merge and compute
m[w, on=c("quarter","exam")][, sum(score*wt), by=.(id,quarter)]
这就是我要做的。
无论如何,如果您想扩大季度数,您应该将加权规则明确存储在某个地方,而不是即时输入。