数据帧中连续零的计数

时间:2017-12-29 14:49:38

标签: r dataframe

以下是我的数据框。它有行名和列名。

       1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   row1 0 0 0 1 0 0 1 0 0  0  0  0  0  0  0
   row2 0 0 0 1 1 1 1 1 1  1  1  1  1  1  0 

我想基于连续的零(来自最后一列,每行的列)派生一个 test 列。下面是一个示例。对于第一行,有8个连续的零,所以 test 行中的值应为8.对于第二行,结果应该是1只有一个零。(我想从15开始考虑并回到零开始的地方) 。

       1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 test
   row1 0 0 0 1 0 0 1 0 0  0  0  0  0  0  0  8
   row2 0 0 0 1 1 1 1 1 1  1  1  1  1  1  0  1

实现这一目标的最佳方式是什么?

2 个答案:

答案 0 :(得分:4)

使用 SELECT i.eventtype, i.evtdate , i.tod , COUNT( * ) AS count FROM eventinfo AS i LEFT JOIN entries as e On e.eventcat = i.eventtype GROUP BY i.eventtype, i.evtdate , i.tod ; 的解决方案:

rle

说明:

使用getConsecZeroRle <- function(x) { foo <- rle(x) foo$lengths[tail(which(foo$values), 1)] } result <- apply(df[, -1] == 0, 1, function(x) getConsecZeroRle(x)) df$test <- as.numeric(result) df$test[is.na(df$test)] <- 0 迭代数据框的子集。对于每一行,计算连续零(apply)的长度,并使用rle提取最后一个值。没有零的行将生成tail(使用NA)以零替换它们。

使用is.na(df$test)的解决方案:

sum

说明:

提取每行中的最后getConsecZeroSum <- function(x) { x[1:tail(which(!x), 1)] <- FALSE sum(x) } df$test <- apply(df[, -1] == 0, 1, function(x) getConsecZeroSum(x)) 值,然后将所有内容转换为FALSEFALSE),然后使用x[1:tail(which(!x), 1)] <- FALSE从最后计算零值。

结果:

sum

答案 1 :(得分:1)

你可以简单地找到不等于0的第一个值的索引(从最后一列开始)然后减去一个:

df$test2 <- apply(df[,ncol(df):1]==0, 1, which.min) - 1

df
#  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 test2
#1 0 0 0 1 0 0 1 0 0  0  0  0  0  0  0     8
#2 0 0 0 1 1 1 1 1 1  1  1  1  1  1  0     1

另一个答案:

由于我对没有apply行的方法感到好奇,因此我提出了一个(公认的复杂)Reduce解决方案。不是我推荐的解决方案,但我有兴趣看看是否有办法做到这一点:

iniCol <- setNames(df[,ncol(df)] == 0, as.numeric(df[,ncol(df)] == 0))
df$test2 <- Reduce(function(ini, add) {temp <- ifelse(pmin(as.numeric(names(ini)), add==0) == 0, ini, rowSums(cbind(ini, add == 0)))
                                       ini  <- setNames(temp, pmin(as.numeric(names(ini)), add==0))}, 
                   df[,(ncol(df)-1):1], 
                   ini = iniCol)

这背后的想法是使用names属性来跟踪列是否曾0。如果是,那么我们就停止计数,否则继续计数。