在R中,统计数据框中每一行特定值的连续出现次数

3
我有一个月度变量值的 data.frame,包含很多地点的数据(所以有很多行),我想计算有几个连续的月份(即连续的单元格)值为零。如果仅从左到右读取,这将是容易的,但增加了一些复杂性,即年底与年初相连。
例如,在下面简化的数据集中(用季节代替月份),地点1有3个“0”月,地点2有2个,“3”没有任何一个。
df<-cbind(location= c(1,2,3),
Winter=c(0,0,3),
Spring=c(0,2,4),
Summer=c(0,2,7),
Autumn=c(3,0,4))

我该如何计算这些连续的零值?我查看了rle,但目前仍然一知半解!

非常感谢任何帮助:)


据我理解,您想为每个位置计算这个? - Andriy T.
你的数据集中是否可能存在不连续的零值?因为这种情况在示例中没有提供。 - David Arenburg
是的,那是可能的。我应该在我的示例中包含它,抱歉! - kim1801
2个回答

2

您已经确定了最长连续行的两种情况:(1)在中间位置,或者(2)跨越每一行的结尾和开头。因此,您需要计算每个条件并取最大值,如下所示:

df<-cbind(
Winter=c(0,0,3),
Spring=c(0,2,4),
Summer=c(0,2,7),
Autumn=c(3,0,4))

#>      Winter Spring Summer Autumn
#> [1,]      0      0      0      3
#> [2,]      0      2      2      0
#> [3,]      3      4      7      4


# calculate the number of consecutive zeros at the start and end
startZeros  <-  apply(df,1,function(x)which.min(x==0)-1)
#> [1] 3 1 0
endZeros  <-  apply(df,1,function(x)which.min(rev(x==0))-1)
#> [1] 0 1 0

# calculate the longest run of zeros
longestRun  <-  apply(df,1,function(x){
                y = rle(x);
                max(y$lengths[y$values==0],0)}))
#> [1] 3 1 0

# take the max of the two values
pmax(longestRun,startZeros +endZeros  )
#> [1] 3 2 0

当然,更简单的解决方案是:
longestRun  <-  apply(cbind(df,df),# tricky way to wrap the zeros from the start to the end
                      1,# the margin over which to apply the summary function
                      function(x){# the summary function
                          y = rle(x);
                          max(y$lengths[y$values==0],
                              0)#include zero incase there are no zeros in y$values
                      })

请注意,上述解决方案有效是因为我的df不包括location字段(列)。

太棒了!唯一我能挑剔的是当只有零时,它会循环两次来计算24(而不是12,我使用的是月份而不是季节!)但这很容易解决。非常感谢! - kim1801

2

试试这个:

df <- data.frame(location = c(1, 2, 3),
                 Winter = c(0, 0, 3),
                 Spring = c(0, 2, 4),
                 Summer = c(0, 2, 7),
                 Autumn = c(3, 0, 4))

maxcumzero <- function(x) {
    l <- x == 0
    max(cumsum(l) - cummax(cumsum(l) * !l))
}

df$N.Consec <- apply(cbind(df[, -1], df[, -1]), 1, maxcumzero)

df
#   location Winter Spring Summer Autumn N.Consec
# 1        1      0      0      0      3        3
# 2        2      0      2      2      0        2
# 3        3      3      4      7      4        0

这将向数据帧添加一列,指定在数据帧的每行中连续出现零的最大次数。数据帧被列绑定到自身,以便能够检测秋季和冬季之间的连续零。

这里使用的方法基于Martin Morgan在他对类似问题的回答


@DavidArenburg:您能举个例子说明它不起作用的情况吗?在我所有的测试中,它都符合预期。 - Alex A.
它没有考虑到年份的开始和结束。请查看其他答案中的结果。应该是3 2 0而不是3 1 0 - David Arenburg
你可以尝试通过执行 apply(cbind(df[, ncol(df), drop = FALSE], df[, -c(1, ncol(df))]), 1, maxcumzero) 来解决这个问题,但不确定它的美观程度。 - David Arenburg
嗯,我不是很喜欢这个修复方法(虽然它似乎有效)。你看到 cbind(df[, -1], df[, -1]) 的结果了吗? - David Arenburg
@DavidArenburg:我同意这不是一个理想的解决方案,但它确保了所有季节都是连续的。我尝试了你建议的修复方法,在这种情况下它确实有效,但我看到的问题是夏季和秋季不再连续。 - Alex A.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接