`sapply` 对 "zoo" 对象成功但对 "xts" 对象不成功,为什么?
`sapply` is successful for "zoo" object but not "xts" object, why?
这是一个显示 "zoo" 和 "xts" 之间明显区别的示例。
library(xts)
mydf = as.data.frame(replicate(6, sample(c(1:10), 10, rep = T)))
myzoo = zoo(mydf, order.by = Sys.Date() + 1:10)
resultzoo = sapply(myzoo, function(x) x+1)
虽然我丢失了日期(这是已经评论过的行为 here),但上面的代码工作正常。但是,下面的代码给出了错误
myxts = xts(mydf, order.by = Sys.Date() + 1:10)
resultxts = sapply(myxts, function(x) x+1)
# Error in array(r, dim = d, dimnames = if (!(is.null(n1 <- names(x[[1L]])) & :
# length of 'dimnames' [1] not equal to array extent
我找不到对这种奇怪行为的任何解释。欢迎任何想法。
我觉得你提出了一个很好的问题。在回答之前,我想评论一下你可以使用
sapply(myzoo, "+", 1)
sapply(myxts, "+", 1)
而不是
sapply(myzoo, function (x) x + 1)
sapply(myxts, function (x) x + 1)
这是因为 "+"
已经是一个函数。试试 1 + 2
和 "+"(1, 2)
.
sapply
需要两个阶段。第一阶段是对 lapply
的普通调用;第二阶段是调用 simplify2array
来简化结果。您收到的错误消息表明在第二阶段发生了错误。事实上,如果我们尝试:
x1 <- lapply(myzoo, "+", 1)
x2 <- lapply(myxts, "+", 1)
我们完全没有错误!
但是,如果我们比较 x1
和 x2
,我们就会看到不同之处。为了整洁起见,我只提取第一个列表元素:
x1[[1]]
#2016-09-30 2016-10-01 2016-10-02 2016-10-03 2016-10-04 2016-10-05 2016-10-06
# 3 4 5 7 2 2 4
#2016-10-07 2016-10-08 2016-10-09
# 3 5 3
x2[[1]]
# V1
#2016-09-30 3
#2016-10-01 4
#2016-10-02 5
#2016-10-03 7
#2016-10-04 2
#2016-10-05 2
#2016-10-06 4
#2016-10-07 3
#2016-10-08 5
#2016-10-09 3
啊,对于 "zoo" 对象,降维了所以我们得到了一个向量;而对于 "xts" 对象,维度没有下降,因此我们得到一个单列矩阵!
正是由于这个原因,sapply
失败了。默认情况下,sapply
的简化选项是 simplify = TRUE
,它总是尝试简化为一维向量或二维矩阵。对于x1
,这没有问题;但对于 x2
,这是不可能的。
如果我们使用更温和的设置:simplify = "array"
,我们将得到适当的行为:
sapply(myzoo, "+", 1, simplify = "array")
给出一个二维数组(即你看到的矩阵);
sapply(myxts, "+", 1, simplify = "array")
给出一个 3D 数组.
从这个例子中,我们可以看出 sapply
并不总是可取的。为什么不使用以下内容:
y1 <- do.call(cbind, x1)
y2 <- do.call(cbind, x2)
# V1 V2 V3 V4 V5 V6
#2016-09-30 3 8 6 4 11 3
#2016-10-01 4 3 9 2 5 7
#2016-10-02 5 7 9 7 7 10
#2016-10-03 7 2 5 3 5 3
#2016-10-04 2 6 7 2 4 5
#2016-10-05 2 2 11 2 4 7
#2016-10-06 4 3 10 10 8 2
#2016-10-07 3 6 4 5 9 4
#2016-10-08 5 4 10 10 3 8
#2016-10-09 3 3 11 8 11 7
它们给出相同的输出,而且您得到的是日期作为行名!更有什者,原物class为尊!
class(y1)
# [1] "zoo"
class(y2)
# [1] "xts" "zoo"
跟进
Out of curiosity....is there a function for the *apply
family doing the equivalent of your two step procedure (i.e. lapply
+ do.call
)?
好像不是。您可以从 ?lapply
获取所有这些(包括 "See Also" 部分)。如果真的有,这个网站上的人就不会经常做 lapply
+ do.call
组合了。
这是一个显示 "zoo" 和 "xts" 之间明显区别的示例。
library(xts)
mydf = as.data.frame(replicate(6, sample(c(1:10), 10, rep = T)))
myzoo = zoo(mydf, order.by = Sys.Date() + 1:10)
resultzoo = sapply(myzoo, function(x) x+1)
虽然我丢失了日期(这是已经评论过的行为 here),但上面的代码工作正常。但是,下面的代码给出了错误
myxts = xts(mydf, order.by = Sys.Date() + 1:10)
resultxts = sapply(myxts, function(x) x+1)
# Error in array(r, dim = d, dimnames = if (!(is.null(n1 <- names(x[[1L]])) & :
# length of 'dimnames' [1] not equal to array extent
我找不到对这种奇怪行为的任何解释。欢迎任何想法。
我觉得你提出了一个很好的问题。在回答之前,我想评论一下你可以使用
sapply(myzoo, "+", 1)
sapply(myxts, "+", 1)
而不是
sapply(myzoo, function (x) x + 1)
sapply(myxts, function (x) x + 1)
这是因为 "+"
已经是一个函数。试试 1 + 2
和 "+"(1, 2)
.
sapply
需要两个阶段。第一阶段是对 lapply
的普通调用;第二阶段是调用 simplify2array
来简化结果。您收到的错误消息表明在第二阶段发生了错误。事实上,如果我们尝试:
x1 <- lapply(myzoo, "+", 1)
x2 <- lapply(myxts, "+", 1)
我们完全没有错误!
但是,如果我们比较 x1
和 x2
,我们就会看到不同之处。为了整洁起见,我只提取第一个列表元素:
x1[[1]]
#2016-09-30 2016-10-01 2016-10-02 2016-10-03 2016-10-04 2016-10-05 2016-10-06
# 3 4 5 7 2 2 4
#2016-10-07 2016-10-08 2016-10-09
# 3 5 3
x2[[1]]
# V1
#2016-09-30 3
#2016-10-01 4
#2016-10-02 5
#2016-10-03 7
#2016-10-04 2
#2016-10-05 2
#2016-10-06 4
#2016-10-07 3
#2016-10-08 5
#2016-10-09 3
啊,对于 "zoo" 对象,降维了所以我们得到了一个向量;而对于 "xts" 对象,维度没有下降,因此我们得到一个单列矩阵!
正是由于这个原因,sapply
失败了。默认情况下,sapply
的简化选项是 simplify = TRUE
,它总是尝试简化为一维向量或二维矩阵。对于x1
,这没有问题;但对于 x2
,这是不可能的。
如果我们使用更温和的设置:simplify = "array"
,我们将得到适当的行为:
sapply(myzoo, "+", 1, simplify = "array")
给出一个二维数组(即你看到的矩阵);sapply(myxts, "+", 1, simplify = "array")
给出一个 3D 数组.
从这个例子中,我们可以看出 sapply
并不总是可取的。为什么不使用以下内容:
y1 <- do.call(cbind, x1)
y2 <- do.call(cbind, x2)
# V1 V2 V3 V4 V5 V6
#2016-09-30 3 8 6 4 11 3
#2016-10-01 4 3 9 2 5 7
#2016-10-02 5 7 9 7 7 10
#2016-10-03 7 2 5 3 5 3
#2016-10-04 2 6 7 2 4 5
#2016-10-05 2 2 11 2 4 7
#2016-10-06 4 3 10 10 8 2
#2016-10-07 3 6 4 5 9 4
#2016-10-08 5 4 10 10 3 8
#2016-10-09 3 3 11 8 11 7
它们给出相同的输出,而且您得到的是日期作为行名!更有什者,原物class为尊!
class(y1)
# [1] "zoo"
class(y2)
# [1] "xts" "zoo"
跟进
Out of curiosity....is there a function for the
*apply
family doing the equivalent of your two step procedure (i.e.lapply
+do.call
)?
好像不是。您可以从 ?lapply
获取所有这些(包括 "See Also" 部分)。如果真的有,这个网站上的人就不会经常做 lapply
+ do.call
组合了。