2016-09-29 5 views
2

"zoo"と "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) 

私は(すでに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 

私はこの奇妙な動作の説明が見つかりません。どんな考えも大歓迎です。

+0

'sapply'は最初の引数' X'のリストで呼び出されることに注意してください。そして、もしXでないなら、 'X'はリストに強制されます。 zoo/xtsオブジェクトで 'sapply'を呼び出すより良い代替方法は' apply(X、2、FUN) 'を使って列をループすることです。 –

答えて

3

あなたは非常に良い質問を提起したと思います。私の答えを行う前に、私はあなたが"+"が既に機能であるため、これは代わりに

sapply(myzoo, function (x) x + 1) 
sapply(myxts, function (x) x + 1) 

sapply(myzoo, "+", 1) 
sapply(myxts, "+", 1) 

を使用することができることをコメントしたいと思います。 1 + 2"+"(1, 2)を試してください。


sapplyは2段階を要する。最初の段階はlapplyへの通常の呼び出しです。第2段階は結果の簡素化のためにsimplify2arrayへの呼び出しです。あなたが得るエラーメッセージは、何か間違ったことが第2段階で起こることを発表します。実際に試してみると:

x1 <- lapply(myzoo, "+", 1) 
x2 <- lapply(myxts, "+", 1) 

エラーは一度も発生しません。

ただし、x1x2を比較すると、その違いがわかります。 「動物園」は、オブジェクトが、寸法は、我々はベクトルを取得するようにドロップされるため

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の簡略化オプションはsimplify = TRUEで、常に1Dベクトルまたは2D行列に単純化しようとします。 x1については、これは問題ありません。しかし、x2の場合、これは不可能です。私たちは穏やかな設定を使用する場合

  1. sapply(myzoo, "+", 1, simplify = "array")が2D配列を与える(すなわち、あなたが見る行列);:simplify = "array"を、我々は適切な行動を取得します
  2. 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" 
好奇心のうち

フォローアップ

....あなたの2つの段階の手順と同等のものをやって*apply家族のための機能があります(つまりlapply + do.call )?

そうではありません。 ?lapply(「参照」の部分を含む)からすべてを取得することができます。実際にあれば、このサイトの人々はしばしばlapply + do.callの組み合わせをしません。

+0

詳細な回答をいただきありがとうございます。本当に役に立ちました。好奇心から...あなたの2つのステップの手続き(すなわちlapply + do.call)に相当する「適用」ファミリーのための関数はありますか? –

関連する問題