先日参加した1細胞RNAseq解析勉強会は基本的なRプログラミングとシーケンサーから少し前処理したあとのリード数データの取り扱いについての講義であった。司会の先生が格好良くライブコーディングを披露されていたのでそれを観察していたのだが、一般的なオブジェクトに対してcolSumsを適用する場面があり面食らった。
具体的には
library(scater) importFrom(Biobase,"pData<-") sce <- newSCESet(countData=all.counts) x <- pData(sce) colSums(x)
のような感じだったと記憶している。ダックタイピングが行われており、xはSCESetクラスのオブジェクトなのだが、matrixやdata.frameに対して実行されるcolSums関数が適用できてしまっている。S4クラスなら以下のように実装すれば良さそう。ExpressionSetというスーパークラスを継承しているので実際にはBioconductorの中身を調べる必要があるが、詳細を調べてはいないので注意。
以下のコードではstructクラス、struct2クラスを実装した。containsは継承元のクラスを指定する。
# ただのS4クラスだと「cannot coerce type 'S4' to vector of type 'matrix'」というエラーが出る。 # 実装例その1(おそらくこちらに近い) setClass("struct", contains = "matrix", representation=representation( version="numeric" ) ) newStruct <- function(mat, version) { new("struct", mat, version=version) } a <- newStruct(matrix(1:4, nrow=2)), 0.01) colSums(a) # 実装例その2(SetGenericを無限に繰り返す必要があり微妙) setClass("struct2", representation = representation( data = "matrix", version = "numeric" ), prototype = prototype ( data = matrix(0, 0, 0), version = 0 ) ) as.matrix.struct <- function(object) { object@data } setGeneric("as.matrix", def = as.matrix.struct) b <- new("struct2", data=matrix(1:4, nrow=2), version=0.1) as.matrix(b)
- 参考
- S4クラスなど
- data.frameを拡張するには 成功編(S4でふつうに) - Technically, technophobic.
- Rのクラス(S3~R6) - tak0kadaの何でもノート
- 総称的関数 |: setMethodという関数もあるようです(調べていない)
- scaterの該当コード
- 勉強会の元ネタ記事
- S4クラスなど
ところでR3.4でjitコンパイラが標準になったらしいですね。R3.3ではSpeed up your R code using a just-in-time (JIT) compiler | R-statistics blogを使えば早くなるのでしょうか。メモリ消費量も減るとなお良さそうです。R言語徹底解説を読めばこの手の問題は解決しそうですがC++に時間をかけているのでまたそのうち。
- その他
- PEP 544 -- Protocols: Structural subtyping (static duck typing) | Python.org: pythonでのducktypingが気になってきた…