rollapply() 由 n 个月
rollapply() by n-months
我正在寻找一种使用 rollapply 将系列拆分为 n 个月的序列的方法。假设您有以下内容:
z <- zoo(101:465, as.Date(1:365))
as.data.frame(z)
我想获取每个 n 个月的索引值向量(或列表)列表,以便我可以处理数据...很像宽度参数在 rollapply 中实现,除了宽度在这个大小写是可变的(取决于一个月中的天数)。
注意:更喜欢 base-R 解决方案,但看到其他可以使用的库会很有趣
不确定,我没听错。但也许这可行:
# create data
z <- zoo::zoo(101:465, as.Date(1:365))
# everything you need is cut it by quarter
quarters <- cut(as.Date(index(z)), breaks = 'quarter', labels = F)
# but if you want list of indices, you make them this way
idxs <- split(seq_along(z), quarters)
# to see what you've got
dplyr::glimpse(idxs)
List of 5
$ 1: int [1:89] 1 2 3 4 5 6 7 8 9 10 ...
$ 2: int [1:91] 90 91 92 93 94 95 96 97 98 99 ...
$ 3: int [1:92] 181 182 183 184 185 186 187 188 189 190 ...
$ 4: int [1:92] 273 274 275 276 277 278 279 280 281 282 ...
$ 5: int 365
最终为动物园对象滚动了我自己的 rollapply():
辅助函数
get.months.elapsed <- function(start.date, end.date) {
ed <- as.POSIXlt(end.date)
sd <- as.POSIXlt(start.date)
12 * (ed$year - sd$year) + (ed$mon - sd$mon)
}
1.向前滚动 WINDOW:
rollapply.list.date.range <- function(data, num.of.months, FUN)
{
dates.list <- index(data)
seq.list <- sapply(dates.list, FUN = function(x) {
dt <- as.integer(x[1])
cur.seq.list <- separate.by.months(dt, dates.list, num.of.months)
names(cur.seq.list) <- dt
return(cur.seq.list)
})
lapply(seq.list, FUN)
}
separate.by.months <- function(dt, dates.list, num.of.months)
{
date.seq.indexes <- sapply(dates.list, function(x) {
date.diff <- as.integer(x) - dt
date.normalized <- get.months.elapsed(as.Date(0), as.Date(date.diff))
floor(date.normalized / num.of.months)
})
seq.list <- split(dates.list, date.seq.indexes)
seq.list["0"]
}
2。反向滚动 WINDOW:
rollapply.date.range <- function(data, num.of.months, FUN)
{
dates.list <- rev(index(data))
seq.list <- sapply(dates.list, FUN = function(x) {
dt <- x[1]
cur.seq.list <- separate.by.months(dt, dates.list, num.of.months)
names(cur.seq.list) <- dt
return(cur.seq.list)
})
lapply(seq.list, FUN)
}
separate.by.months <- function(dt, dates.list, num.of.months)
{
date.seq.indexes <- sapply(dates.list, function(x) {
date.diff <- as.integer(x) - as.integer(dt)
date.normalized <- ifelse(sign(date.diff) == 1, -9999, -get.months.elapsed(as.Date(0), as.Date(date.diff)))
floor(date.normalized / num.of.months)
})
seq.list <- split(dates.list, date.seq.indexes)
seq.list["0"]
}
然后你会这样称呼它:
rollapply.list.date.range(z, 3, mean)
1。聚合
如果您正在寻找的是您对问题的回答中的代码描述的处理,那么您正在寻找的最好描述为聚合而不是函数的滚动应用程序。
要获取每个月、每个季度和每个 n 个月的平均值,请使用 aggregate.zoo
:
myfun <- mean
aggregate(z, as.yearmon, myfun)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## 115.5 144.5 174.0 204.5 235.0 265.5 296.0 327.0
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 357.5 388.0 418.5 449.0 465.0
aggregate(z, as.yearqtr, myfun)
## 1970 Q1 1970 Q2 1970 Q3 1970 Q4 1971 Q1
## 145.0 235.0 326.5 418.5 465.0
n <- 3
aggregate(z, as.Date(cut(index(z), paste(n, "months"))), myfun)
## 1970-01-01 1970-04-01 1970-07-01 1970-10-01 1971-01-01
## 145.0 235.0 326.5 418.5 465.0
或使用 as.yearmon
代替 as.Date
。上面的mean
可以换成任意函数。
2。滚动应用
a) 如果你真的想滚动 n 个月然后创建一个动物园对象 ag
每个月一行 31 列填充额外的列在 NA 的短短几个月。然后 运行 rollapplyr
使用一个函数将每次迭代的数据分解为一个长向量,删除在短月份结束时添加的 NA,并将其输入我们的任意函数。
n <- 3
myfun <- mean
ag <- aggregate(z, as.yearmon, "length<-", value = 31)
rollapplyr(ag, n, function(x) myfun(na.omit(c(t(x)))), fill = NA, by.column = FALSE)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
b)另一种可能是:
s <- split(z, as.yearmon(index(z)))
r <- rollapplyr(seq_along(s), n, function(ix) myfun(unlist(s[ix])), fill = NA)
zoo(r, as.yearmon(names(s), "%b %Y"))
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
3。 rollapply 均值
以下使用均值,但取决于您的任意函数是什么,它们可能可以修改以使用它。
a) 首先,创建一个 2 列的动物园对象 ag
,其行是每个月的总和和长度,然后在该对象上使用 rollapplyr
.
n <- 3
ag2 <- aggregate(z, as.yearmon, function(x) c(sum(x), length(x)))
rollapplyr(ag2, 3, function(x) sum(x[, 1]) / sum(x[, 2]), fill = NA, by.column = FALSE)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
b) 或者另一种方法是创建一个复杂的动物园对象 ag3
其实部和虚部是每个月的总和和天数以及在上面使用 rollapplyr
:
ag3 <- aggregate(z, as.yearmon, function(x) complex(real = sum(x), imag = length(x)))
rollapplyr(ag3, 3, function(x) sum(Re(x)) / sum(Im(x)), fill = NA)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
我正在寻找一种使用 rollapply 将系列拆分为 n 个月的序列的方法。假设您有以下内容:
z <- zoo(101:465, as.Date(1:365))
as.data.frame(z)
我想获取每个 n 个月的索引值向量(或列表)列表,以便我可以处理数据...很像宽度参数在 rollapply 中实现,除了宽度在这个大小写是可变的(取决于一个月中的天数)。
注意:更喜欢 base-R 解决方案,但看到其他可以使用的库会很有趣
不确定,我没听错。但也许这可行:
# create data
z <- zoo::zoo(101:465, as.Date(1:365))
# everything you need is cut it by quarter
quarters <- cut(as.Date(index(z)), breaks = 'quarter', labels = F)
# but if you want list of indices, you make them this way
idxs <- split(seq_along(z), quarters)
# to see what you've got
dplyr::glimpse(idxs)
List of 5
$ 1: int [1:89] 1 2 3 4 5 6 7 8 9 10 ...
$ 2: int [1:91] 90 91 92 93 94 95 96 97 98 99 ...
$ 3: int [1:92] 181 182 183 184 185 186 187 188 189 190 ...
$ 4: int [1:92] 273 274 275 276 277 278 279 280 281 282 ...
$ 5: int 365
最终为动物园对象滚动了我自己的 rollapply():
辅助函数
get.months.elapsed <- function(start.date, end.date) {
ed <- as.POSIXlt(end.date)
sd <- as.POSIXlt(start.date)
12 * (ed$year - sd$year) + (ed$mon - sd$mon)
}
1.向前滚动 WINDOW:
rollapply.list.date.range <- function(data, num.of.months, FUN)
{
dates.list <- index(data)
seq.list <- sapply(dates.list, FUN = function(x) {
dt <- as.integer(x[1])
cur.seq.list <- separate.by.months(dt, dates.list, num.of.months)
names(cur.seq.list) <- dt
return(cur.seq.list)
})
lapply(seq.list, FUN)
}
separate.by.months <- function(dt, dates.list, num.of.months)
{
date.seq.indexes <- sapply(dates.list, function(x) {
date.diff <- as.integer(x) - dt
date.normalized <- get.months.elapsed(as.Date(0), as.Date(date.diff))
floor(date.normalized / num.of.months)
})
seq.list <- split(dates.list, date.seq.indexes)
seq.list["0"]
}
2。反向滚动 WINDOW:
rollapply.date.range <- function(data, num.of.months, FUN)
{
dates.list <- rev(index(data))
seq.list <- sapply(dates.list, FUN = function(x) {
dt <- x[1]
cur.seq.list <- separate.by.months(dt, dates.list, num.of.months)
names(cur.seq.list) <- dt
return(cur.seq.list)
})
lapply(seq.list, FUN)
}
separate.by.months <- function(dt, dates.list, num.of.months)
{
date.seq.indexes <- sapply(dates.list, function(x) {
date.diff <- as.integer(x) - as.integer(dt)
date.normalized <- ifelse(sign(date.diff) == 1, -9999, -get.months.elapsed(as.Date(0), as.Date(date.diff)))
floor(date.normalized / num.of.months)
})
seq.list <- split(dates.list, date.seq.indexes)
seq.list["0"]
}
然后你会这样称呼它:
rollapply.list.date.range(z, 3, mean)
1。聚合
如果您正在寻找的是您对问题的回答中的代码描述的处理,那么您正在寻找的最好描述为聚合而不是函数的滚动应用程序。
要获取每个月、每个季度和每个 n 个月的平均值,请使用 aggregate.zoo
:
myfun <- mean
aggregate(z, as.yearmon, myfun)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## 115.5 144.5 174.0 204.5 235.0 265.5 296.0 327.0
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 357.5 388.0 418.5 449.0 465.0
aggregate(z, as.yearqtr, myfun)
## 1970 Q1 1970 Q2 1970 Q3 1970 Q4 1971 Q1
## 145.0 235.0 326.5 418.5 465.0
n <- 3
aggregate(z, as.Date(cut(index(z), paste(n, "months"))), myfun)
## 1970-01-01 1970-04-01 1970-07-01 1970-10-01 1971-01-01
## 145.0 235.0 326.5 418.5 465.0
或使用 as.yearmon
代替 as.Date
。上面的mean
可以换成任意函数。
2。滚动应用
a) 如果你真的想滚动 n 个月然后创建一个动物园对象 ag
每个月一行 31 列填充额外的列在 NA 的短短几个月。然后 运行 rollapplyr
使用一个函数将每次迭代的数据分解为一个长向量,删除在短月份结束时添加的 NA,并将其输入我们的任意函数。
n <- 3
myfun <- mean
ag <- aggregate(z, as.yearmon, "length<-", value = 31)
rollapplyr(ag, n, function(x) myfun(na.omit(c(t(x)))), fill = NA, by.column = FALSE)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
b)另一种可能是:
s <- split(z, as.yearmon(index(z)))
r <- rollapplyr(seq_along(s), n, function(ix) myfun(unlist(s[ix])), fill = NA)
zoo(r, as.yearmon(names(s), "%b %Y"))
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
3。 rollapply 均值
以下使用均值,但取决于您的任意函数是什么,它们可能可以修改以使用它。
a) 首先,创建一个 2 列的动物园对象 ag
,其行是每个月的总和和长度,然后在该对象上使用 rollapplyr
.
n <- 3
ag2 <- aggregate(z, as.yearmon, function(x) c(sum(x), length(x)))
rollapplyr(ag2, 3, function(x) sum(x[, 1]) / sum(x[, 2]), fill = NA, by.column = FALSE)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5
b) 或者另一种方法是创建一个复杂的动物园对象 ag3
其实部和虚部是每个月的总和和天数以及在上面使用 rollapplyr
:
ag3 <- aggregate(z, as.yearmon, function(x) complex(real = sum(x), imag = length(x)))
rollapplyr(ag3, 3, function(x) sum(Re(x)) / sum(Im(x)), fill = NA)
## Jan 1970 Feb 1970 Mar 1970 Apr 1970 May 1970 Jun 1970 Jul 1970 Aug 1970
## NA NA 145.0 175.0 204.5 235.0 265.5 296.5
## Sep 1970 Oct 1970 Nov 1970 Dec 1970 Jan 1971
## 326.5 357.5 388.0 418.5 434.5