2011-03-31 33 views
2

我想編寫一個處理多種數據類型的函數。下面是一個有效的例子,但看起來很笨拙。有沒有一個標準(或更好)的方式來做到這一點?編寫函數來處理R/Splus中的多種數據類型?

(它的幾次都是這樣我錯過了Matlab的這裏的一切都是一種類型:>)

myfunc = function(x) { 
    # does some stuff to x and returns a value 
    # at some point the function will need to find out the number of elements 
    # at some point the function will need to access an element of x. 
    # 
    # args: 
    # x: a column of data taking on many possible types 
    #  e.g., vector, matrix, data.frame, timeSeries, list 
    x.vec <- as.vector(as.matrix(as.data.frame(x))) 
    n <- length(x.vec) 
    ret <- x.vec[n/3] # this line only for concreteness 
    return(ret) 
} 
+0

語言只有一種類型我發瘋;-)。班級是你的朋友,讓你處理好事情和靈活。如下所述使用R的OO功能。 S3方法非常輕巧,實際上增加了很少的額外工作。作爲交換,你會得到美妙的行爲,就像能夠對任何事情調用summary()一樣。 – 2011-03-31 23:52:44

回答

6

使用S3方法。一個簡單的例子,讓你開始:

myfunc <- function(x) { 
    UseMethod("myfunc",x) 
} 
myfunc.data.frame <- function(x) { 
    x.vec <- as.vector(as.matrix(x)) 
    myfunc(x.vec) 
} 
myfunc.numeric <- function(x) { 
    n <- length(x) 
    ret <- x[n/3] 
    return(ret) 
} 
myfunc.default <- function(x) { 
    stop("myfunc not defined for class",class(x),"\n") 
} 

有兩點需要注意:

  1. ...語法傳遞給函數的任何額外的參數。如果要擴展現有的S3方法(例如,寫入類似summary.myobject的東西),那麼包含...是一個好主意,因爲您可以傳遞傳統給定規範函數的參數。

print.myclass <- function(x,...) { print(x$keyData,...) }

  1. 您可以從其他函數調用功能,並保持整潔,簡約。
+0

在函數簽名中始終包含'...'不是一個好主意,因爲如果拼錯了參數名稱,您將永遠不會收到錯誤消息。 – hadley 2011-04-01 02:35:05

+0

@哈德利:我似乎記得錢伯斯書中的一本書說明這是一個好習慣,但我絕對相信你所有的東西都是R!如果我能找到它,我會看看如果我不能很快查找它並且發佈更多關於它的邏輯。 – 2011-04-01 02:37:43

+0

這個問題是否需要額外的參數。如果你不需要傳遞額外的參數到其他方法,那麼你根本不需要......。其中一個缺點是,您承諾不會爲您的方法提供任何其他參數。所以有一個選擇,@哈德利的評論提到使用'...'的缺點 – 2011-04-02 17:43:10

3

嗯,你對函數文檔是

# args: 
# x: a column of data taking on many possible types 
#  e.g., vector, matrix, data.frame, timeSeries, list 

並且如果一個作爲供給您聲稱需要的對象,是不是已經是矢量,而不是一個矩陣或數據幀,因此避免需要單獨的方法/具體處理?

> dat <- data.frame(A = 1:10, B = runif(10)) 
> class(dat[,1]) 
[1] "integer" 
> is.vector(dat[,1]) 
[1] TRUE 
> is.vector(dat$A) 
[1] TRUE 
> is.numeric(dat$A) 
[1] TRUE 
> is.data.frame(dat$A) 
[1] FALSE 

我想:

myfunc <- function(x) { 
    # args: 
    # x: a column of data taking on many possible types 
    #  e.g., vector, matrix, data.frame, timeSeries, list 
    n <- length(x) 
    ret <- x[n/3] # this line only for concreteness 
    return(ret) 
} 

> myfunc(dat[,1]) 
[1] 3 

現在,如果你要處理不同類型的對象,並提取一列,然後S3方法將是很長的路要走。也許你的例子在實際使用中已經過於簡化了?無論如何,S3的方法將是這樣的:

myfunc <- function(x, ...) 
    UseMethod("myfunc", x) 

myfunc.matrix <- function(x, j = 1, ...) { 
    x <- x[, j] 
    myfunc.default(x, ...) 
} 

myfunc.data.frame <- function(x, j = 1, ...) { 
    x <- data.matrix(x) 
    myfunc.matrix(x, j, ...) 
} 

myfunc.default <- function(x, ...) { 
    n <- length(x) 
    x[n/3] 
} 

,並提供:

> myfunc(dat) 
[1] 3 
> myfunc(data.matrix(dat)) 
[1] 3 
> myfunc(data.matrix(dat), j = 2) 
[1] 0.2789631 
> myfunc(dat[,2]) 
[1] 0.2789631 
相關問題