r - data.table 使用列前瞻的逐行操作
问题描述
假设我有以下数据:
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)]
所以数据表是这样的:
> 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
我想在“firstnonzero”指示的列右侧找到非零元素的数量。
所需的输出将是:
> tempmat
prod1vint1 prod1vint2 prod1vint3 prod1vint4 firstnonzero numbernonzero
1: 0 0 0 0 NA NA
2: 1 1 0 4 1 2
3: 1 0 0 4 1 1
4: 0 1 0 4 2 1
5: 0 1 1 4 2 2
6: 0 1 0 5 2 1
这是因为,例如,在第 2 行,prod1vint2 和 prod1vint4 中有一个非零元素,因此第一个非零元素右侧的非零元素的数量为 2,以此类推。
我正在尝试找到一个高效且可扩展的解决方案,因此它不能是我可以自己实现的应用或循环样式解决方案。
解决方案
由于您要为每一行计算相当多的统计信息,因此您可能需要考虑使用Rcpp
如下:
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
这应该很快。
推荐阅读
- javascript - 掩蔽复选框的标签 - 正确的方法?
- angular - Angular ControlValueAccessor 在(更改)事件中触发旧值
- cordova - 在 Ionic 3 中使用非原生 cordova 插件
- twitter-bootstrap - 具有引导模式的 Fullcalendar 创建多个事件
- reactjs - JSX:内联条件属性 [href]
- html - 如何防止在 HTML 中单击重新加载按钮时重新提交表单
- r - R中使用先验函数的关联规则
- java - 如何用“\\”分割字符串
- excel - 我们如何在 angular6 中显示 excel 和 doc 文件
- javascript - JSON 数据未出现在数据表中。单击任何功能时,它说没有可用的数据