#r #dataframe #xts #zoo #sapply
#r #фрейм данных #xts #зоопарк #sapply
Вопрос:
Вот пример, который показывает четкое различие между «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)
Хотя я теряю дату (это поведение уже прокомментировано здесь), приведенный выше код работает нормально. Однако приведенный ниже код выдает ошибку
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]])) amp; :
# length of 'dimnames' [1] not equal to array extent
Я не могу найти никакого объяснения этому странному поведению. Любая идея приветствуется.
Комментарии:
1. Обратите внимание, что
sapply
это должно вызываться со списком для первого аргумента,X
. ИX
будет принудительно преобразован в список, если он не один. Лучшей альтернативой вызовуsapply
объекта zoo / xts является просто использованиеapply(X, 2, FUN)
для перебора столбцов.
Ответ №1:
Я думаю, вы подняли очень хороший вопрос. Прежде чем ответить, я хотел бы прокомментировать, что вы можете использовать
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
Ах, для объекта «зоопарк» измерение отбрасывается, поэтому мы получаем вектор; в то время как для объекта «xts» измерение не отбрасывается, следовательно, мы получаем матрицу с одним столбцом!
Именно по этой причине sapply
происходит сбой. По умолчанию опция упрощения для sapply
is simplify = TRUE
, которая всегда пытается упростить до 1D-вектора или 2D-матрицы. Для x1
этого нет проблем; но для x2
этого это невозможно.
Если мы используем более мягкую настройку: simplify = "array"
, мы получим соответствующее поведение:
sapply(myzoo, " ", 1, simplify = "array")
выдает 2D-массив (т. Е. Матрицу, Которую вы видите);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(y1)
# [1] "zoo"
class(y2)
# [1] "xts" "zoo"
Последующие действия
Из curiosity….is есть ли функция для
*apply
семьи, выполняющая эквивалент вашей двухэтапной процедуры (т.е.lapply
do.call
)?
Кажется, нет. Вы можете получить их все ?lapply
(включая часть «См. Также»). Если это действительно так, люди на этом сайте не будут так lapply
do.call
часто использовать комбинацию .
Комментарии:
1. Большое спасибо за ваш подробный ответ. Действительно полезно. Из curiosity….is есть ли функция для семейства «применить», выполняющая эквивалент вашей двухэтапной процедуры (т.е. lapply do.call)?