使用rle和for循环的最长连续时间段高于阈值

问题描述 投票:1回答:1

我有四年的流量数据一个月,我试图弄清楚如何在四年中的每一年中提取最长连续时间或超过某个阈值。在下面的示例中,阈值为4.我想尝试使用for循环或可能的一个apply函数来完成此操作,但我不确定如何去做。

这是我的示例数据帧:

year <- c(rep(2009,31), rep(2010, 31), rep(2011, 31), rep(2012, 31))
day<-c(rep(seq(1:31),4))
discharge <- c(4,4,4,5,6,5,4,8,4,5,3,8,8,8,8,8,8,8,1,2,2,8,8,8,8,8,8,8,8,8,4,4,4,5,6,3,1,1,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,10,3,3,3,3,3,3,1,1,3,8,8,8,8,8,8,8,8,8,1,2,2,8,8,3,8,8,8,8,8,8,4,4,4,5,6,3,1,1,3,3,3,3,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,3)

df<-data.frame(cbind(year, day, discharge))
df$threshold<-ifelse(discharge>=4,1,0)

在该示例中,如果放电处于或高于阈值,则将阈值列编码为1,否则将阈值编码为0。我能够部分获得我想要的输出一年(2009年在下面的例子中),使用以下代码:

rl2009<-with(subset(df,year==2009),rle(threshold))
cs2009 <- cumsum(rl2009$lengths)
index2009<-cbind(cs2009[rl2009$values == 1] - rl2009$length[rl2009$values == 1] + 1,
cs2009[rl2009$values == 1])
df2009<-data.frame(index2009)
df2009 #ouput all periods when flow is above threshold
df2009$X3<-df2009$X2-df2009$X1+1

max2009<-df2009[which.max(df2009$X3),]
max2009 #output the first and longest period when flow is above threshold

对于2009年,有三个时间段,排放等于或超过4,但选择从第1天到第10天的时间段,因为它是超过阈值的最长时间段中的第一个。 X1表示时间段的开始,X2表示时间段的结束,X3表示时间段的天数。如果有多个具有相同天数的期间,我想选择第一个期间。

我所需的四年产量如下:

year   X1  X2  X3
2009    1  10  10
2010    9  31  23
2011   10  18   9
2012   12  30  19

实际数据包括更多年和许多流,因此每年单独执行此操作是不可行的。如果有人对如何实现这一点有任何想法,我们将不胜感激。谢谢。

r loops apply
1个回答
0
投票

简单地说,使用诸如threshold_find之类的已定义函数来概括您的过程,并将每年子集化的数据帧传递到其中,这可以使用by进行处理。

作为tapply的面向对象的包装器,by按一个或多个因子(即年份)对数据帧进行切片,并返回定义的函数输出的任何对象的列表,这里是最大数据帧。最后,do.call()行将by列表中的所有数据帧绑定到一个数据帧中。

threshold_find <- function(df) {
  rl <- with(df, rle(threshold))      
  cs <- cumsum(rl$lengths)

  index <- cbind(cs[rl$values == 1] - rl$length[rl$values == 1] + 1,
                 cs[rl$values == 1])
  df <- data.frame(index)
  df$X3 <- df$X2 - df$X1+1

  max <- df[which.max(df$X3),]
  max      
}

finaldf <- do.call(rbind, by(df, df$year, FUN=threshold_find))

finaldf
#      X1 X2 X3
# 2009  1 10 10
# 2010  9 31 23
# 2011 10 18  9
# 2012 12 30 19
© www.soinside.com 2019 - 2024. All rights reserved.