1

(クラス'spec')Rから返されたオブジェクトを(強制?)新しいS4クラスに変換したいのですが。stats::spectrumS3クラスの「spec」は、基本的に、さまざまな形式のさまざまな情報のリストです(画面出力にコメントしました)。

psd3 <- spectrum(rnorm(1e3), plot=FALSE)
summary(psd3)
#           Length Class  Mode     
# freq      500    -none- numeric  
# spec      500    -none- numeric  
# coh         0    -none- NULL     
# phase       0    -none- NULL     
# kernel      0    -none- NULL     
# df          1    -none- numeric  
# bandwidth   1    -none- numeric  
# n.used      1    -none- numeric  
# orig.n      1    -none- numeric  
# series      1    -none- character
# snames      0    -none- NULL     
# method      1    -none- character
# taper       1    -none- numeric  
# pad         1    -none- numeric  
# detrend     1    -none- logical  
# demean      1    -none- logical 

class(unclass(psd3))
# [1] "list"

is.object(psd3) & !isS4(psd3)
# [1] TRUE

ここで、「specS4」という名前のクラスに新しいS4ジェネレーターを定義するとします。ここで、スロット名は「spec」オブジェクトの名前です。

specS4 <- setClass("specS4",
  representation = representation(freq="numeric", spec="numeric", coh="numeric", phase="numeric", kernel="numeric", df="numeric", bandwidth="numeric", n.used="numeric", orig.n="numeric", series="character", snames="character", method="character", taper="numeric", pad="numeric", detrend="logical", demean="logical"), 
  prototype = prototype(coh=numeric(0), phase=numeric(0), kernel=numeric(0), df=Inf, snames="", detrend=FALSE, demean=FALSE)
)

そしてそれから新しいオブジェクトを生成します:

psd4 <- specS4()

validObject(psd4)
# [1] TRUE

psd3の各コンポーネントを対応するスロットに割り当てる最良の方法は何でしょうpsd4か。 複雑なのは、いくつかの(既知の)フィールドにspectrum戻る可能性があることです。これらの値を割り当てると、 (指定された表現に対して)NULLエラーがスローされます。checkSlotAssignment

私が持っている苦痛な解決策は次のとおりです。

nonull.spec <- function(psd){
  stopifnot(inherits(psd, 'spec', FALSE))
  # as.numeric(NULL) --> numeric(0)
  # spec.pgram/.ar both may return NULL for these:
  psd$coh <- as.numeric(psd$coh)
  psd$phase <- as.numeric(psd$phase)
  psd$kernel <- as.numeric(psd$kernel)
  psd$snames <- as.character(psd$snames)
  return(psd)
}

as.specS4 <- function(psd) UseMethod("as.specS4")
as.specS4.spec <- function(psd){
  stopifnot(inherits(psd, 'spec', FALSE))
  ## deal with possible NULLs
  psd <- nonull.spec(psd)
  ## generate specS4 class
  S4spec <- specS4()
  ## (re)assign from 'spec' list
  S4spec@freq <- psd$freq
  S4spec@spec <- psd$spec
  S4spec@coh <- psd$coh
  S4spec@phase <- psd$phase
  S4spec@kernel <- psd$kernel
  S4spec@snames <- psd$snames
  # [more to assign, obviously]
  # 
  # [run a validity check...]
  #
  return(S4spec)
}

as.specS4.spec意図的に不完全ですが、これは機能します。

psd4c <- as.specS4(psd3)

validObject(psd4c)
# [1] TRUE

何を達成するためのより良い方法はありas.specS4.specますか?この解決策は不安定なようです。

4

1 に答える 1

1

私はこれが実際にどれほど単純であるかを理解しました。ドー!

slotNames'specS4'オブジェクトと'spec'オブジェクトを一致させてから、names次のように割り当てますslot(質問のコードが実行されたと仮定します)。

as.specS4.spec <- function(psd){
  stopifnot(inherits(psd, 'spec', FALSE))
  psd <- nonull.spec(psd)
  S4spec <- specS4() 
  spec_slots <- slotNames(S4spec)
  spec_slots <- spec_slots[match(names(psd), spec_slots)]
  for (what in spec_slots){
    slot(S4spec, what) <- as.vector(unlist(psd[what]))
  }
  return(S4spec)
}

psd4c2 <- as.specS4(psd3)

validObject(psd4c2)
# [1] TRUE
> all.equal(psd4c@freq, psd4c2@freq, psd3$freq)
# [1] TRUE
于 2013-01-03T06:14:57.177 に答える