基于R中的多个索引进行应用

tapply based on multiple indexes in R

我有一个数据框,很像这个:

ref=rep(c("A","B"),each=240)
year=rep(rep(2014:2015,each=120),2)
month=rep(rep(1:12,each=10),4)
values=c(rep(NA,200),rnorm(100,2,1),rep(NA,50),rnorm(40,4,2),rep(NA,90))

DF=data.frame(ref,year,month,values)

我想计算每年每个参考文献的最大连续 NA 数。 我创建了一个函数,它计算出连续NA的最大数量,但只能基于一个变量。

例如,

func <-   function(x) { 
  max(rle(is.na(x))$lengths) 
} 

with(DF, tapply(values,ref, func))
# A   B 
# 200  90 

with(DF, tapply(values,year, func))
# 2014 2015 
# 120   90

所以在ref A中总共最多有200个连续的NA,在ref B中最多有90个,这是正确的。 2014年还有120个NA,2015年有90个

我想要的是每个 ref 和年份的结果,例如:

A 2015 80
A 2014 120
B 2015 90
B 2014 50

有多种方法可以做到这一点,一种是使用 plyr 库:

library(plyr)
ddply(DF,c('ref','year'),summarise,NAs=max(rle(is.na(values))$lengths))

  ref year NAs
1   A 2014 120
2   A 2015  80
3   B 2014  60
4   B 2015  90

使用你的函数,你也可以试试:

with(DF, tapply(values,list(ref,year), func))

输出略有不同

  2014 2015
A  120   80
B   60   90

通过使用 melt(),您可以获得相同的数据帧。

我喜欢食谱格式

library(dplyr)

DF$values[is.na(DF$values)] <- 1   

DF %>% 
 filter(values==1) %>%  
 group_by(ref,year) %>% 
 mutate(csum=cumsum(values)) %>% 
 group_by(ref,year) %>% 
 summarise(max(csum))

Source: local data frame [4 x 3]
Groups: ref [?]

     ref  year max(csum)
   (fctr) (int)     (dbl)
1      A  2014       120
2      A  2015        80
3      B  2014        50
4      B  2015        90

与上面的 tapply 解决方案非常相似。不过,我发现 aggregate 的输出比 tapply 更好。

with(DF, aggregate(list(Value = values),list(Year = year,ref = ref), func))

  Year  ref  Value
1 2014   A   120
2 2015   A    80
3 2014   B    60
4 2015   B    90