2013-08-07 27 views
0

我有一個包含幾個矩陣的某個類的對象,我想構建一個函數來訪問並可能修改這個矩陣的子集。例如:如何編寫分配給調用環境對象的R函數?

foo<-list(x=diag(1:4),y=matrix(1:8,2,4)) 
class(foo)<-"bar" 
attr(foo,"m")<-4 
attr(foo,"p")<-2 
rownames(foo$x)<-colnames(foo$x)<-colnames(foo$y)<-c("a.1","b.1","b.2","c.1") 
attr(foo,"types")<-c("a","b","b","c") 

現在我可以訪問和修改某些內容是這樣的:

foo$x[attr(foo,"types")%in%c("c","b"),attr(foo,"types")%in%c("c","b")]  
foo$x[attr(foo,"types")%in%c("c","b"),attr(foo,"types")%in%c("c","b")]<-matrix(5,3,3) 

但不是上述情況,我想構建以下類型的功能:

modify<-function(object,element,types){ 
    # check that the object is proper class, 
    # and the element and the types are found in the object 

    # this returns to the local copy of the corresponding subset: 
    object[[element]][attr(object,"types")%in%types,attr(object,"types")%in%types]  
} 

對於訪問上述功能是好的,但如果我想修改原始對象呢?顯然這不起作用:

modify(foo,"x",c("c","b"))<-matrix(5,3,3) 
Error in modify(foo, "x", c("c", "b")) <- matrix(5, 3, 3) : 
    could not find function "modify<- 

是否有可能以某種方式得到這項工作?如果不是,我可以考慮的一個選項是將參數replace.with添加到功能modify,然後將分配首先分配給本地副本,然後使用assign函數將更改複製到呼叫環境中的對象。爲此,我需要在調用環境中找到原始對象,但我不知道如何做到這一點。

回答

0

好吧,我找到了自己的解決方案與舊文章的幫助下R-help by Brian Ripley:

foo<-list(x=diag(1:4),y=matrix(1:8,2,4)) 
class(foo)<-"bar" 
attr(foo,"m")<-4 
attr(foo,"p")<-2 
rownames(foo$x)<-colnames(foo$x)<-colnames(foo$y)<-c("a.1","b.1","b.2","c.1") 
attr(foo,"types")<-c("a","b","b","c") 

`modify<-` <- function(x, element, subset,value) UseMethod("modify<-") 
`modify<-.bar` <- function(x, element, subset,value) { 

    x[[element]][,attr(foo,"types")%in%subset] <- value 
    x } 

modify(foo,"x",c("c","b"))<-matrix(5,3,3) 
foo$x 
    a.1 b.1 b.2 c.1 
a.1 1 0 0 0 
b.1 0 5 5 5 
b.2 0 5 5 5 
c.1 0 5 5 5 
1

需要提醒的是,這是通常在,你可以使用下面的皺起了眉頭:

從目標環境中,變量設置爲環境,然後傳遞作爲參數傳遞給你的功能,你可以在使用assignget

en <- environment() 
myfunc <- function(..., en=en) { 
    . etc . 
    assign("varname", envir=en) 
} 

請注意,如果你只是改變屬性,則data.table包的setattr功能已經很好地實現了這句話:

setattr(x,name,value) 
+0

如果你只是改變屬性,內置'ATTR <-'做精,並在地方修改。我不確定'setattr'有什麼優點。 – hadley

+0

謝謝,但問題在於,原始對象的名稱,即「varname」可以是任意的。 –

+0

@Hemmo,這是個什麼問題?使用帶引號的變量'assign' –