我有四年的流量数据一个月,我试图弄清楚如何在四年中的每一年中提取最长连续时间或超过某个阈值。在下面的示例中,阈值为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
实际数据包括更多年份和许多流,因此每年单独执行此操作是不可行的。如果有人对如何实现这一点有任何想法,我们将不胜感激。感谢。
答案 0 :(得分:0)
简单地说,使用已定义的函数(例如 threshold_find )来概括您的流程,并将每年的子集化数据框传递到其中,可以使用by
进行处理。
作为tapply
的面向对象的包装器,by
按一个或多个因子(即 year )对数据帧进行切片,并返回定义的任何对象的列表函数输出,这里是 max 数据帧。最后,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