首先是一些样本数据
yr1 <- sample(0:1, 365, replace = T)
yr2 <- sample(0:1, 365, replace = T)
yr3 <- sample(0:1, 365, replace = T)
yr4 <- sample(0:1, 365, replace = T)
value <- c(yr1, yr2, yr3, yr4)
yr <- rep(2000:2003, each = 365)
doy <- rep(1:365, times = 4)
foo <- as.data.frame(cbind(value, yr, doy))
foo
包含3列。第1列的任意值为1或0.第2列包含年份,第3列包含一年中的某一天(365天)
我有两个载体,包括朱利安时代的开始和结束日期
start <- c(258, 258,258,258)
mid <- c(279, 281,285,288)
end <- c(286, 295,300,320)
range.val <- as.data.frame(cbind(start, mid, end))
range.val$yr<- c(2000, 2001, 2002, 2003)
range.val
给了我julian天,我必须在foo
之间总结每年的值。
例如,对于2000年,我需要从258天到279天,然后从279到286总和foo$value
。同样,
2001年,总和foo$value
从258到281,然后从281到295。
我还需要计算每年这些指数之间最长连续出现1的长度。
我这样做了:
for(yr in 2000:2003){
range.sub <- range.val[range.val$yr == yr,]
foo.sub <- foo[foo$yr == yr,]
sum.1 <- sum(foo.sub[range.sub$start:range.sub$mid,"value"])
sum.2 <- sum(foo.sub[range.sub$mid:range.sub$end,"value"])
length.1 <- rle(foo.sub[range.sub$start:range.sub$mid,"value"])
max.spell.length <- max(sort(length.1$lengths, , decreasing = TRUE))
length.1 <- rle(foo.sub[range.sub$mid:range.sub$start,"value"])
max.spell.length1 <- max(sort(length.1$lengths, , decreasing = TRUE))
}
在我不断努力减少使用for循环的过程中,我想知道是否可以使用其他函数来缩短上面的代码。
答案 0 :(得分:1)
这是使用dplyr的解决方案。
创建一个联合数据框&amp;指示每个yr-doy组合是在范围1(从开始到中间),范围2(从中到开),还是两者都没有。
heroes
对于每年范围X的总值,过滤范围&amp;按年总结:
library(dplyr)
df <- left_join(foo, range.val, by = "yr")
df <- df %>%
mutate(in.range1 = doy >= start & doy <= mid,
in.range2 = doy >= mid & doy <= end)
# Note: I'm not sure if the ranges are supposed to be inclusive on both ends, but you
# should be able to change that easily
对于最长的1次,过滤范围&amp;对每年的值进行df.sum.1 <- df %>%
filter(in.range1) %>% #change to in.range2 for mid-end
group_by(yr) %>%
summarise(value = sum(value))
> df.sum.1
# A tibble: 4 x 2
yr value
<dbl> <int>
1 2000 12
2 2001 12
3 2002 10
4 2003 10
。请注意,我们应首先过滤值== 1,否则如果有更长的0,则可能会改为:
rle
(为了重现性,样本数据是使用df.spell.length1 <- df %>%
filter(in.range1) %>% #change to in.range2 for mid-end
group_by(yr) %>%
arrange(doy) %>%
do(data.frame(unclass(rle(.$value)))) %>%
filter(values == 1) %>%
filter(lengths == max(lengths)) %>%
unique()
> df.spell.length1
# A tibble: 4 x 3
# Groups: yr [4]
yr lengths values
<dbl> <int> <int>
1 2000 7 1
2 2001 3 1
3 2002 3 1
4 2003 3 1
生成的。)