9

いくつかの拡張機能 (追加の関数、追加のプロパティ) を備えた、ほとんどデータ フレームであるクラスを作成したいと考えています。クラスは基本的にデータ フレームですが、そのデータ フレームのスキーマ (以下では「フォーム」と呼ばれる、自動派生、データ フレームとして表され、データ フレームを適切な型にキャストするために使用される) などの追加の属性があります。他にもいくつかあります。ユーザーがこのオブジェクトを、その特別な型を認識しない他の関数で使用する場合、オブジェクトの data.frame 部分を処理するようにしてください。これを行う最善の方法は何ですか?

私が見つけた 2 つの方法はどちらも不十分です。それらと、私がまだ見て解決しようとしている問題をリストします。質問は、私がやろうとしていることを行うための最良の方法は何ですか?

方法 1、「data.frame」を「ベース」スロットとして使用する (この SO 投稿に触発された)

setClass("formhubData", representation(form="data.frame"), contains="data.frame")
fd <- new('formhubData', data.frame(x=c(1,2)), form=data.frame(name='x', type='select one', label='X'))

このメソッドを使用すると、次のようなことができます。

fd$x                  >> 1 2
names(fd)             >> "x"

[更新: 「故障」は、異なる引数で setClass('formhubData', ...) を繰り返し呼び出していた私の環境が原因であることが判明しました。新しい R セッションでは、以下の関数はすべて期待どおりに動作します。]

しかし、それはすぐに壊れます:

nrow(fd)              >> NULL
colnames(fd)          >> NULL

上記のリンクの投稿とは異なり、単純なものでもis.data.frameうまくいきません

is.data.frame         >> FALSE

方法 2、「データ」スロットを使用する(SP に触発された)

setClass("formhubData", representation(data="data.frame", form="data.frame"))
fd <- new('formhubData', data=data.frame(x=c(1,2)), form=data.frame(name='x', type='select one', label='X'))

デフォルトの定義を失います:

fd$x             >> NULL
names(fd)        >> integer(0)

しかし、少なくともそれらのほとんどを再定義できます ([、[[ などについてはまだ学習する必要があります)。

 dim.formhubData <- function(x) dim(x@data)
 names.formhubData <- function(x) names(x@data)
 nrow(fd)        >> 2
 names(fd)       >> "x"

ただし、data.frame を受け取るメソッドについては、@data スロットへのパススルーとしてクラスを使用する必要があるという事実を表現できないようです。*.formhubData <- function(x, ...) *(x, ...)クラスのクライアントが使用する可能性のあるすべての関数を推測してdim.formhubDatanames.formhubData、 などのように定義するのではなく、のようなものが必要だと感じて います。

このようなことを達成する方法はありますか?

4

1 に答える 1

1

どちらのアプローチもある程度は機能しますが、実際には方法 2 をお勧めします。「is-a」設計と「has-a」設計に関する「標準的な」オブジェクト指向の考慮事項は、一般に「has-a」に有利に働きます。さらに、R ではいつでもメソッドをオブジェクトに追加できるため、ある意味で「is-a」は、クラスに対して任意のことをいくつでも行うことが理にかなっていることを宣伝しています。これは、サブセット化のような定義された関数であっても、実現するのが難しい契約です。おそらく、ユーザーが行または列を の基dataになる にドロップ/追加したformhubData場合、 の情報を更新したいと思うでしょうform

代わりに、'has-a' 関係を実装し、その機会を利用して、意味のある操作へのインターフェイスを制限したいようです。基礎となる実装への単純なディスパッチにより、最小限の新しいコードで実質的なコードの再利用を引き続き得ることができます。

setMethod(dim, "formhubData", function(x) dim(x@data)

nrowたとえば、とが得ncolられます。一般的な操作 (サブセット化など) では、データ構造の整合性を尊重する実装を提供したいと考えています。そして、ユーザーがほとんど任意のことを実行できる必要がある場合は、単純な「アクセサー」を に提供できます。おそらくセッターを使用して、フィールドを更新された data.frame と一致さdataせるために必要なことを何でも実行できます。formユーザーによって提供されます。

于 2013-05-05T20:24:48.897 に答える