5

最大4つの異なるタイプで到着するデータを処理するパッケージを構築しています。これらの各タイプは、matrix、data.frame、またはtreeの形式の正当なクラスです。データの処理方法やその他の実験的要因によっては、これらのデータコンポーネントの一部が欠落している場合がありますが、この情報を特別なクラスのインスタンスとして保存し、異なるコンポーネントを認識するメソッドを持つことができると、非常に便利です。データ。

アプローチ1:

ネストされたツリーのように見える増分継承構造を実験しました。データ型の各組み合わせには、明示的に定義された独自のクラスがあります。これを将来追加のデータ型に拡張することは困難であるように思われ、新しい開発者がすべてのクラス名を学習することも困難ですが、それらの名前は適切に編成されている可能性があります。

アプローチ2:

2番目のアプローチは、4つのデータ型すべてのスロットを含む単一の「マスタークラス」を作成することです。欠落データのインスタンスに対してスロットをNULLにできるようにするには、最初にNULLクラスと新しいデータ型クラスの間に仮想クラスユニオンを定義し、次に仮想クラスユニオンを関連するクラスの期待されるクラスとして使用する必要があるようです。マスタークラスのスロット。次に例を示します(各データ型クラスがすでに定義されていると仮定します)。

################################################################################
# Use setClassUnion to define the unholy NULL-data union as a virtual class.
################################################################################    
setClassUnion("dataClass1OrNULL", c("dataClass1", "NULL"))
setClassUnion("dataClass2OrNULL", c("dataClass2", "NULL"))
setClassUnion("dataClass3OrNULL", c("dataClass3", "NULL"))
setClassUnion("dataClass4OrNULL", c("dataClass4", "NULL"))
################################################################################
# Now define the master class with all 4 slots, and 
# also the possibility of empty (NULL) slots and an explicity prototype for
# slots to be set to NULL if they are not provided at instantiation.
################################################################################
setClass(Class="theMasterClass", 
    representation=representation(
        slot1="dataClass1OrNULL",
        slot2="dataClass2OrNULL",
        slot3="dataClass3OrNULL",
        slot4="dataClass4OrNULL"),
    prototype=prototype(slot1=NULL, slot2=NULL, slot3=NULL, slot4=NULL)
)
################################################################################

したがって、質問は次のように言い換えることができます。

これらのアプローチのいずれかに対して、より効率的および/または柔軟な代替手段はありますか?

この例は、スロットのデフォルト値をNULLに設定することに関するSOの質問への回答から変更されています。この質問は、他のすべての空でない場合に特定の複雑なクラスが必要であるにもかかわらず、必要に応じて空にできるスロットを持つクラスを作成するためのRの最良のオプションを知りたいという点で異なります。

4

1 に答える 1

2

私の意見では...

アプローチ2

これは、正式なクラスシステムを採用し、定義が不適切なスロット('A'またはNULL)を含むクラスを作成するという目的をやや無効にします。少なくとも、DataClass1に「NULL」のようなデフォルトを持たせようとします。簡単な例として、ここでのデフォルトは長さゼロの数値ベクトルです。

setClass("DataClass1", representation=representation(x="numeric"))
DataClass1 <- function(x=numeric(), ...) {
    new("DataClass1", x=x, ...)
}

それで

setClass("MasterClass1", representation=representation(dataClass1="DataClass1"))
MasterClass1 <- function(dataClass1=DataClass1(), ...) {
    new("MasterClass1", dataClass1=dataClass1, ...)
}

これの利点の1つは、スロット内のインスタンスがNULLであるか「DataClass1」であるかをメソッドがテストする必要がないことです。

setMethod(length, "DataClass1", function(x) length(x@x))
setMethod(length, "MasterClass1", function(x) length(x@dataClass1))

> length(MasterClass1())
[1] 0
> length(MasterClass1(DataClass1(1:5)))
[1] 5

「空の」スロットにアクセスしたときにユーザーに警告するというコメントに応えて、ユーザーは通常、関数に何か間違ったことを伝えるのではなく、何かを実行させたいと考えていることを思い出してDataClass1()、状態を正確に反映する空のオブジェクトを返すと思います。オブジェクトの。たぶん、showメソッドはスロットのステータスを強化する概要を提供します--DataClass1:none。これは、MasterClass1がいくつかの異なる分析を調整する方法を表している場合に特に適切であるように思われますが、ユーザーはそのうちのいくつかしか実行できません。

このアプローチ(またはアプローチ2)の制限は、メソッドディスパッチを取得できないことです。DataClass1ゼロ以外の長さのインスタンスを持つインスタンスにのみ適切なメソッドを記述できず、いくつかの実行を余儀なくされます。一種の手動ディスパッチ(例:ifまたはswitch)。これは開発者にとっては制限のように思えるかもしれませんが、ユーザーにも当てはまります。ユーザーは、長さがゼロ以外のDataClass1インスタンスを持つMasterClass1のインスタンスにどの操作が一意に適切であるかを理解できません。

アプローチ1

階層内のクラスの名前がユーザーを混乱させると言うとき、これはおそらくより根本的な問題を指しているように思われます。データ型の包括的な表現を作成しようと努力しすぎています。ClassWithMatrixDataFrameAndTreeはデータの表示方法を表していないため、ユーザーはClassWithMatrixDataFrameAndTreeを追跡できなくなります。これはおそらく、あなたの野心を縮小して、あなたが調査している地域の最も顕著な部分だけに実際に取り組む機会です。または、ユーザーが収集したデータをどのように考えて操作するかを再考し、インターフェース(ユーザーに表示されるもの)と実装(ユーザーがどのように表示するか)を分離する機会を利用することもできます。

クラスの名前と数はさておき、「将来、追加のデータ型に拡張するのは難しい」と言うと、S4クラスのニュアンスのいくつかがあなたをつまずかせているのではないかと思います。簡単な解決策は、独自のinitializeメソッドを作成することを避け、コンストラクターに依存して、次のようなトリッキーな作業を行うことです。

setClass("A", representation(x="numeric"))
setClass("B", representation(y="numeric"), contains="A")

A <- function(x = numeric(), ...) new("A", x=x, ...)
B <- function(a = A(), y = numeric(), ...) new("B", a, y=y, ...)

その後

> B(A(1:5), 10)
An object of class "B"
Slot "y":
[1] 10

Slot "x":
[1] 1 2 3 4 5
于 2011-12-01T01:40:42.837 に答える