应用生成 data.frames 列表(或单个 rbinded data.frame)的滚动函数
Apply rolling function which generates a list of data.frames (or single rbinded data.frame)
滚动函数最常用的两个函数(据我所知)是 zoo::rollapply
和 data.table::frollapply()
。
然而,两者似乎都无法 运行 一个为每个步骤生成 data.frame 然后 return 将它们放在列表中或作为单个 rbind
的函数]-ed data.frame.
作为一个简单的例子,如果我有一个函数 return 是一个简单的 data.frame 并且我用滚动函数调用它,我希望得到:
f <- function(x) {
data.frame(a = LETTERS[x], b = x)
}
# will be called twice, with inputs 1:2 and 2:3.
myrollapply(1:3, n = 2, FUN = f)
#> [[1]]
#> a b
#> 1 A 1
#> 2 B 2
#>
#> [[2]]
#> a b
#> 1 B 2
#> 2 C 3
#>
#> -- OR --
#>
#> a b
#> 1 A 1
#> 2 B 2
#> 3 B 2
#> 4 C 3
(对于那些感兴趣的人,我的真实用例是通过一个日期向量(或列表,如果需要的话),然后调用一个外部 API,其中 return 是表格数据. 由于 API 的限制,我不能一次完成所有事情,必须多次调用 API 才能得到我需要的东西。我的最终目标是整理所有 data.frames 我从 API 变成一个 rbind
-ed data.frame.)
zoo
和 data.table
这似乎是不可能的:
zoo
似乎不允许列表作为 zoo
对象,这阻碍了它们用作输入或输出。如果函数 returns 是一个裸体 data.frame,输出似乎是对单个 data.frames 的转置版本进行 rbind
(另外,输出是一个矩阵,而不是data.frame,这是不可接受的)。
zoo::rollapply(c(1, 2, 3),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> a1 a2 a3
#> [1,] 1 2 3
#> [2,] 1 2 3
zoo::rollapply(data.frame(a = c(1, 2, 3)),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> a
#> [1,] 1
#> [2,] 1
#> [3,] 2
#> [4,] 2
#> [5,] 3
#> [6,] 3
zoo::rollapply(c(1, 2, 3),
width = 2,
FUN = function(x) {list(data.frame(a = 1:3))})
#> Error in zoo(do.call("c", dat), index(data)[ix], attr(data, "frequency")) :
#> “x” : attempt to define invalid zoo object
zoo::rollapply(list(1, 2, 3),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> Error in zoo(data) : “x” : attempt to define invalid zoo object
使用data.table::frollapply
,问题更容易理解:return值必须是数字(或可转换为数字)。
data.table::frollapply(c(1, 2, 3), n = 2, FUN = function(x) {data.frame(a = 1:3)})
#> Error in data.table::frollapply(c(1, 2, 3), n = 2, FUN = function(x) { :
#> frollapply: results from provided FUN are not of type double
是否有可以处理这种特殊情况的包或方法?我目前正在使用 for 循环手动完成,但怀疑可能有更好、更像 R 的解决方案。
1) 运行 rollapply
在索引上然后使用 apply
.
library(zoo)
f <- function(x) data.frame(a = LETTERS[x], b = x)
ii <- rollapply(1:3, 2, c)
apply(ii, 1, f)
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
2) 这也有效:
L <- list()
junk <- rollapply(1:3, 2, function(x, i = x[1]) L[[i]] <<- f(x))
L
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
3)另一种方法是在语言上进行计算。
s <- rollapply(1:3, 2, function(x) sprintf("f(c(%s))", toString(x)))
lapply(s, function(x) eval(parse(text = x)))
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
一个简单的滚动切片函数:)
roll_slice <- function(x, w, s){
#' w: window size
#' s: step size
embed(x, w)[seq(1, length(x) - w + 1, by = s), rev(seq_len(w))]
}
apply(roll_slice(c(1, 2, 3), 2, 1), 1, f)
# [[1]]
# a b
# 1 A 1
# 2 B 2
#
# [[2]]
# a b
# 1 B 2
# 2 C 3
救援序列:
## window and number
w <- 2
n <- 2
## generate sequence
s <- rep(seq_len(w)) + rep(seq.int(0, n-1), each=w)
f(s)
# a b
#1 A 1
#2 B 2
#3 B 2
#4 C 3
您可以使用 lapply
应用您自己的滚动功能:
val <- 1:3
k <- 2
lapply(seq_along(head(val, -(k-1))), function(x) f(val[x:(x+k-1)]))
# [[1]]
# a b
#1 A 1
#2 B 2
#[[2]]
# a b
#1 B 2
#2 C 3
另一个例子-
val <- 1:5
k <- 3
lapply(seq_along(head(val, -(k-1))), function(x) f(val[x:(x+k-1)]))
# [[1]]
# a b
#1 A 1
#2 B 2
#3 C 3
#[[2]]
# a b
#1 B 2
#2 C 3
#3 D 4
#[[3]]
# a b
#1 C 3
#2 D 4
#3 E 5
滚动函数最常用的两个函数(据我所知)是 zoo::rollapply
和 data.table::frollapply()
。
然而,两者似乎都无法 运行 一个为每个步骤生成 data.frame 然后 return 将它们放在列表中或作为单个 rbind
的函数]-ed data.frame.
作为一个简单的例子,如果我有一个函数 return 是一个简单的 data.frame 并且我用滚动函数调用它,我希望得到:
f <- function(x) {
data.frame(a = LETTERS[x], b = x)
}
# will be called twice, with inputs 1:2 and 2:3.
myrollapply(1:3, n = 2, FUN = f)
#> [[1]]
#> a b
#> 1 A 1
#> 2 B 2
#>
#> [[2]]
#> a b
#> 1 B 2
#> 2 C 3
#>
#> -- OR --
#>
#> a b
#> 1 A 1
#> 2 B 2
#> 3 B 2
#> 4 C 3
(对于那些感兴趣的人,我的真实用例是通过一个日期向量(或列表,如果需要的话),然后调用一个外部 API,其中 return 是表格数据. 由于 API 的限制,我不能一次完成所有事情,必须多次调用 API 才能得到我需要的东西。我的最终目标是整理所有 data.frames 我从 API 变成一个 rbind
-ed data.frame.)
zoo
和 data.table
这似乎是不可能的:
zoo
似乎不允许列表作为 zoo
对象,这阻碍了它们用作输入或输出。如果函数 returns 是一个裸体 data.frame,输出似乎是对单个 data.frames 的转置版本进行 rbind
(另外,输出是一个矩阵,而不是data.frame,这是不可接受的)。
zoo::rollapply(c(1, 2, 3),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> a1 a2 a3
#> [1,] 1 2 3
#> [2,] 1 2 3
zoo::rollapply(data.frame(a = c(1, 2, 3)),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> a
#> [1,] 1
#> [2,] 1
#> [3,] 2
#> [4,] 2
#> [5,] 3
#> [6,] 3
zoo::rollapply(c(1, 2, 3),
width = 2,
FUN = function(x) {list(data.frame(a = 1:3))})
#> Error in zoo(do.call("c", dat), index(data)[ix], attr(data, "frequency")) :
#> “x” : attempt to define invalid zoo object
zoo::rollapply(list(1, 2, 3),
width = 2,
FUN = function(x) {data.frame(a = 1:3)})
#> Error in zoo(data) : “x” : attempt to define invalid zoo object
使用data.table::frollapply
,问题更容易理解:return值必须是数字(或可转换为数字)。
data.table::frollapply(c(1, 2, 3), n = 2, FUN = function(x) {data.frame(a = 1:3)})
#> Error in data.table::frollapply(c(1, 2, 3), n = 2, FUN = function(x) { :
#> frollapply: results from provided FUN are not of type double
是否有可以处理这种特殊情况的包或方法?我目前正在使用 for 循环手动完成,但怀疑可能有更好、更像 R 的解决方案。
1) 运行 rollapply
在索引上然后使用 apply
.
library(zoo)
f <- function(x) data.frame(a = LETTERS[x], b = x)
ii <- rollapply(1:3, 2, c)
apply(ii, 1, f)
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
2) 这也有效:
L <- list()
junk <- rollapply(1:3, 2, function(x, i = x[1]) L[[i]] <<- f(x))
L
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
3)另一种方法是在语言上进行计算。
s <- rollapply(1:3, 2, function(x) sprintf("f(c(%s))", toString(x)))
lapply(s, function(x) eval(parse(text = x)))
给予:
[[1]]
a b
1 A 1
2 B 2
[[2]]
a b
1 B 2
2 C 3
一个简单的滚动切片函数:)
roll_slice <- function(x, w, s){
#' w: window size
#' s: step size
embed(x, w)[seq(1, length(x) - w + 1, by = s), rev(seq_len(w))]
}
apply(roll_slice(c(1, 2, 3), 2, 1), 1, f)
# [[1]]
# a b
# 1 A 1
# 2 B 2
#
# [[2]]
# a b
# 1 B 2
# 2 C 3
救援序列:
## window and number
w <- 2
n <- 2
## generate sequence
s <- rep(seq_len(w)) + rep(seq.int(0, n-1), each=w)
f(s)
# a b
#1 A 1
#2 B 2
#3 B 2
#4 C 3
您可以使用 lapply
应用您自己的滚动功能:
val <- 1:3
k <- 2
lapply(seq_along(head(val, -(k-1))), function(x) f(val[x:(x+k-1)]))
# [[1]]
# a b
#1 A 1
#2 B 2
#[[2]]
# a b
#1 B 2
#2 C 3
另一个例子-
val <- 1:5
k <- 3
lapply(seq_along(head(val, -(k-1))), function(x) f(val[x:(x+k-1)]))
# [[1]]
# a b
#1 A 1
#2 B 2
#3 C 3
#[[2]]
# a b
#1 B 2
#2 C 3
#3 D 4
#[[3]]
# a b
#1 C 3
#2 D 4
#3 E 5