假设我有以下数据:
differences xs@(_:ys) = zipWith (-) ys xs
因此数据表如下所示:
tempmat=matrix(c(1,1,0,4,1,0,0,4,0,1,0,4, 0,1,1,4, 0,1,0,5),5,4,byrow=T)
tempmat=rbind(rep(0,4),tempmat)
tempmat=data.table(tempmat)
names(tempmat)=paste0('prod1vint',1:4)
tempmat[,firstnonzero:=c(NA,1,1,2,2,2)]
我想在“ firstnonzero”指示的列的右侧找到非零元素的数量。
所需的输出将是:
> tempmat
prod1vint1 prod1vint2 prod1vint3 prod1vint4 firstnonzero
1: 0 0 0 0 NA
2: 1 1 0 4 1
3: 1 0 0 4 1
4: 0 1 0 4 2
5: 0 1 1 4 2
6: 0 1 0 5 2
这是因为,例如,在第2行上,prod1vint2和prod1vint4中有一个非零元素,因此第一个非零元素右侧的非零元素数目为2,依此类推。
我正在尝试找到一个有效且可扩展的解决方案,因此它不能是我可以自己实现的应用或循环风格的解决方案。
答案 0 :(得分:1)
我同意评论中提出的从宽到长重塑建议。不确定如何比较,但这可能是一个开始。
dcast(melt(tempmat[, n := 1L:.N], id.vars = c("firstnonzero", "n"))[,
`:=`(
firstnonzero = which(value != 0L)[1],
numbernonzero = length(which(value != 0L)[-1])),
by = n],
n + firstnonzero + numbernonzero ~ variable)[, n := NULL][]
# firstnonzero numbernonzero prod1vint1 prod1vint2 prod1vint3 prod1vint4
#1: NA 0 0 0 0 0
#2: 1 2 1 1 0 4
#3: 1 1 1 0 0 4
#4: 2 1 0 1 0 4
#5: 2 2 0 1 1 4
#6: 2 1 0 1 0 5
注意:为了使此操作与您提供的样本数据一起使用,我必须将现有的tempmat$firstnonzero
列设为整数向量(请参阅最后的样本数据)。
为了对此进行基准测试,如果您包括(其中的一些)“ 应用或循环样式解决方案,我可以自行实现”。
tempmat=matrix(c(1,1,0,4,1,0,0,4,0,1,0,4, 0,1,1,4, 0,1,0,5),5,4,byrow=T)
tempmat=rbind(rep(0,4),tempmat)
tempmat=data.table(tempmat)
names(tempmat)=paste0('prod1vint',1:4)
tempmat[,firstnonzero:=c(NA,1L,1L,2L,2L,2L)]
答案 1 :(得分:1)
由于您正在为每一行计算大量统计信息,因此您可能需要考虑使用library(Rcpp)
cppFunction('
IntegerMatrix func(IntegerMatrix m) {
int i, j, nr = m.nrow(), nc = m.ncol();
IntegerMatrix res(nr, 3);
for (i=0; i<nr; i++) {
res(i, 0) = -1; //position
res(i, 1) = -1; //count
res(i, 2) = 0; //sum
for (j=0; j<nc; j++) {
if (m(i, j) != 0) {
if (res(i, 0) < 0) {
res(i, 0) = j + 1;
}
if (res(i, 1) >= 0) {
res(i, 2) += m(i, j);
}
res(i, 1) += 1;
}
}
}
return res;
}')
tempmat = matrix(c(1,1,0,4,1,0,0,4,0,1,0,4, 0,1,1,4, 0,1,0,5),5,4,byrow=T)
tempmat = rbind(rep(0,4),tempmat)
cbind(tempmat, func(tempmat))
,如下所示:
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 0 0 0 0 -1 -1 0
[2,] 1 1 0 4 1 2 5
[3,] 1 0 0 4 1 1 4
[4,] 0 1 0 4 2 1 4
[5,] 0 1 1 4 2 2 5
[6,] 0 1 0 5 2 1 5
输出:
select user_id, user_date, Anger, Sadness, Interest
from (select user_id,user_date,emotion, emotion_level
from emotions) as emo
pivot(avg(emotion_level)
for emotion in (Anger, Sadness, Interest)) as P;
这应该很快。