繁体   English   中英

使用列先行进行data.table按行操作

[英]data.table rowwise operations using a column lookahead

假设我有以下数据:

        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,依此类推。

我正在尝试寻找一种有效且可扩展的解决方案,因此它不能是我自己可以实现的应用或循环风格的解决方案。

我同意评论中提出的从宽到长重塑建议的建议。 不确定如何比较,但这可能是一个开始。

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$firstnonzerotempmat$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)]

由于您正在为每一行计算大量统计信息,因此您可能需要考虑使用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

这应该相当快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM