0

我有一个看起来像的数据框

z<-data.frame(a=c(seq(1990,1995,1), 1997,1998,1999,2001,2002,2003), b=seq(90,101,1))

我使用功能

rollapply(b, 3, sd, align='right') 

计算标准差。

我想做的是,如果连续年份之间存在差距,函数会中断并重新开始计算标准差。

编辑:

我的示例输出应如下所示:

enter code here       a   b    c
                 1  1990  90  NA
                 2  1991  91  NA
                 3  1992  92  sd(90,91,92)
                 4  1993  93  sd(93,92,91)
                 5  1994  94  sd(94,93,92)
                 6  1995  95  sd(95,94,93)
                 7  1997  96  NA
                 8  1998  97  NA
                 9  1999  98  sd(98,97,96)
                10  2001  99  NA
                11  2002  100 NA
                12  2003  101 sd(101,100,99)
4

2 回答 2

2

我认为这可以满足您的要求:

my.roll <- function(x) rollapply(x, 3, sd, align='right', fill=NA, na.rm=T)
z$sd <- ave(z$b, c(0, cumsum(diff(z$a) - 1)), FUN=my.roll) 

产生:

      a   b sd
1  1990  90 NA
2  1991  91 NA
3  1992  92  1
4  1993  93  1
5  1994  94  1
6  1995  95  1
7  1997  96 NA
8  1998  97 NA
9  1999  98  1
10 2001  99 NA
11 2002 100 NA
12 2003 101  1

请注意每个间隙后的前两个条目如何为 NA,因为您的窗口中至少需要三个值。

基本上,我们在这里所做的是使用cumsumdiff计算出连续年份的块,然后我们可以用它ave来应用sd到每个块。请注意,如果您有重复的年份(例如 1997 出现 2 次或更多次),或者您的数据未按年份排序,这将中断。

于 2014-02-21T19:12:11.010 回答
1

将 data.frame 转换为 zoo 对象,z并将其与网格合并,g包括所有年份,包括z. 应用rollapplyr它并提取原始时间:

library(zoo)

z <- read.zoo(DF, FUN = identity)
g <- merge(z, zoo(, start(z):end(z)))
r <- rollapplyr(g, 3, sd, fill = NA)[I(time(z))]

给予:

> r
1990 1991 1992 1993 1994 1995 1997 1998 1999 2001 2002 2003 
  NA   NA    1    1    1    1   NA   NA    1   NA   NA    1 

r是一个动物园对象,它time(r)是时间,coredata(r)是数据。

注意:我们使用过:

DF <- structure(list(V1 = c(1990L, 1991L, 1992L, 1993L, 1994L, 1995L, 
  1997L, 1998L, 1999L, 2001L, 2002L, 2003L), V2 = 90:101), .Names = c("V1", 
  "V2"), class = "data.frame", row.names = c(NA, -12L))
于 2014-02-21T20:56:48.733 回答