3

tdtfileを継承するクラス()を定義しましたdata.frame。現在、ではなく[.data.frameクラスの適切なオブジェクトを返すために、同等の置換メソッドを定義しようとしていますが、問題が発生しています。tdtfiledata.frame

これが私がしていることです:

# Define Class
setClass("tdtfile",
  representation(Comment = "character"),
   prototype(Comment = NULL),
   contains = c("data.frame"))

# Construct instance and populate
test <- new("tdtfile",Comment="Blabla")
df <- data.frame(A=seq(26),B=LETTERS)
for(sName in names(getSlots("data.frame"))){
  slot(test,sName) <- slot(df,sName)
}

# "Normal" data.frame behavior (loss of slot "Comment")
str(test[1])
# Works as well - will be trying to use that below
`[.data.frame`(test,1)

# Try to change replacement method in order to preserve slot structure 
# while accessing data.frame functionality
setMethod(
  `[`,
  signature=signature(x="tdtfile"),
  function(x, ...){
    # Save the original
    storedtdt <- x
    # Use the fact that x is a subclass to "data.frame"
    tmpDF <- `[.data.frame`(x, ...)
    # Reintegrate the results
    if(inherits(x=tmpDF,what="data.frame")){
      for(sName in names(getSlots("data.frame"))){
        slot(storedtdt,sName) <- slot(tmpDF,sName)
      }
      return(storedtdt)
    } else {
      return(tmpDF)
    }
  })

# Method does not work - data.frame remains complete. WHY?
str(test[1])

# Cleanup
#removeMethod(
#  `[`,
#  signature=signature(x="tdtfile"))

のようなものを呼び出すとき

tdtfile[1]

これは、最初の列だけでなく、tdtfileすべての列が含まれているオブジェクトを返します...誰かが私が欠けているものを見つけることができますか?data.frame

ご協力ありがとうございました。

よろしくお願いいたします。

4

1 に答える 1

1

メソッドが誤動作している理由は、、、iおよびjがメソッドdrop内で自動的に使用可能になるためです。これは、ジェネリック[がどのように機能するかの結果であると私は信じています。これは、に依存するのではなく、[これらの引数を名前で渡す必要があることを意味します。残念ながら、これにより、さまざまな形式のインデックスを正しく処理する責任が発生します。[.data.frame...

これはまともな仕事をする修正されたメソッド定義ですが、drop引数の特定の使用法の下で純粋なデータフレームのインデックス付けとまったく同じように動作しない場合があります。

setMethod(
    `[`,
    signature=signature(x="tdtfile"),
    function(x, ...){
        # Save the original
        storedtdt <- x
        # Use the fact that x is a subclass to "data.frame"
        Nargs <- nargs()
        hasdrop <- "drop" %in% names(sys.call())
        if(Nargs==2) {
            tmpDF <- `[.data.frame`(x, i=TRUE, j=i, ..., drop=FALSE)
        } else if((Nargs==3 && hasdrop)) {
            tmpDF <- `[.data.frame`(x, i=TRUE, j=i, ..., drop)
        } else if(hasdrop) {
            tmpDF <- `[.data.frame`(x, i, j, ..., drop)
        } else {
            tmpDF <- `[.data.frame`(x, i, j, ...)
        }
        # Reintegrate the results
        if (inherits(x=tmpDF, what="data.frame")){
            for(sName in names(getSlots("data.frame"))){
                slot(storedtdt, sName) <- slot(tmpDF, sName)
            }
            return(storedtdt)
        } else {
            return(tmpDF)
        }
    })

テストオブジェクトのいくつかの例:

> head(test[1])
Object of class "tdtfile"
  A
1 1
2 2
3 3
4 4
5 5
6 6
Slot "Comment":
[1] "Blabla"

> test[1:2,]
Object of class "tdtfile"
  A B
1 1 A
2 2 B
Slot "Comment":
[1] "Blabla"

これを行うためのより標準的な方法があるかどうかはわかりません。おそらく、いくつかのS4パッケージのソースコードを調べてみてください。

編集:これは、上記の抽出方法と同様の精神的な置換方法です。これは、オブジェクトを直接呼び出す前に、オブジェクトをデータフレームに明示的に強制します。[<-これは、主に、オブジェクトを呼び出す場合に発生する警告を回避するためです[<-.data.frame。繰り返しになりますが、動作は純粋なデータフレームの置換方法と完全に同じではありませんが、より多くの作業を行うことでそうすることができます。

setMethod(
    `[<-`,
    signature=signature(x="tdtfile"),
    function(x, ..., value){
        # Save the original
        storedtdt <- x
        # Use the fact that x is a subclass to "data.frame"
        Nargs <- nargs()
        if (any(!names(sys.call()) %in% c("", "i", "j", "value"))) {
            stop("extra arguments are not allowed")
        }
        tmpDF <- data.frame(x)
        if(Nargs==3) {
             if (missing(i)) i <- j
             tmpDF[i] <- value
        } else if(Nargs==4) {
             tmpDF[i, j] <- value
        }
        # Reintegrate the results
        for(sName in names(getSlots("data.frame"))){
            slot(storedtdt, sName) <- slot(tmpDF, sName)
        }   
        return(storedtdt)
    })

例:

> test[2] <- letters
> test[1,"B"] <- "z"
> test$A[1:3] <- 99
> head(test)
Object of class "tdtfile"
   A B
1 99 z
2 99 b
3 99 c
4  4 d
5  5 e
6  6 f
Slot "Comment":
[1] "Blabla"

余談ですが、抽出/置換がデータフレームの場合とまったく同じように機能することが重要な場合は、data.frameをスーパークラスとして使用するのではなく、データフレームを含むスロットを持つようにクラスを書き換えることを検討します。継承をめぐる構成!

于 2013-02-25T08:57:46.153 に答える