2013-10-30 28 views
2

不同的R的對象類屬性,當我寫了一個簡單的C函數在R,它採取對象類中的任何對象,並且返回與inline使用。我曾試圖按照Writing R Extensions手冊,其中規定不一致性得到用C函數

getAttribsetAttrib功能,獲取和設置單獨的屬性。他們的第二個參數是SEXP,它在我們想要的屬性的符號表中定義了名稱;這些和許多這樣的符號在頭文件Rinternals.h中定義。

另外它還指出..

在R中的class只是命名"class",因此它可以作爲這樣的處理的屬性。

所以我寫了這個...

# required package 
require(inline) 

# Simple C function to get "class" attribute of an R object 
classC <- cfunction(c(x = "ANY") , ' 

    SEXP out; 
    PROTECT(out = allocVector(STRSXP, 1)); 
    SET_STRING_ELT(out, 0, mkChar("class")); 
    UNPROTECT(1); 
    return getAttrib(x, out) ; 

') 

但測試它在各種不同類型的[R對象有時會返回class,但通常返回NULL。我沒有看到它確實在工作的對象類型之間的連接,所以不知道在哪裏出了問題......

# Various classes of objects 
con <- file("text.txt") 
d <- data.frame(a = 1) 
e <- new.env() 
f <- y ~ 1 
fun <- function(x) x^2 
i <- 1L:10L 
l <- list(1 , 2 , 3) 
m <- matrix(1 , 10 , 10) 
n <- runif(1) 
v <- 1:10 

和運行我得到的功能...

# Output from the function 
classC(con) 
#[1] "file"  "connection" 
classC(d) 
#[1] "data.frame" 
classC(e) 
#NULL 
classC(f) 
#[1] "formula" 
classC(fun) 
NULL 
classC(i) 
NULL 
classC(l) 
#NULL 
classC(m) 
#NULL 
classC(n) 
#NULL 
classC(v) 
#NULL 

我錯過了什麼?我很感興趣,因爲我最終希望編寫一個輔助函數,該函數返回globalenvironment中所有對象名稱的矢量,它們是特定的class。但主要是我自己的好奇心和學習,我知道我可以做這樣的事情:

sapply(ls() , function(x) class(get(x))) 

回答

2

文檔在於:)你做什麼就相當於R函數:

classR = function(x) attributes(x)$class 

當你調用class [R確實是這樣的:

SEXP R_data_class(SEXP obj, Rboolean singleString) 
{ 
    SEXP value, klass = getAttrib(obj, R_ClassSymbol); 
    int n = length(klass); 
    if(n == 1 || (n > 0 && !singleString)) 
     return(klass); 
    if(n == 0) { 
     SEXP dim = getAttrib(obj, R_DimSymbol); 
     int nd = length(dim); 
     if(nd > 0) { 
      if(nd == 2) 
       klass = mkChar("matrix"); 
      else 
       klass = mkChar("array"); 
     } 
     else { 
      SEXPTYPE t = TYPEOF(obj); 
      switch(t) { 
      case CLOSXP: case SPECIALSXP: case BUILTINSXP: 
      klass = mkChar("function"); 
      break; 
      case REALSXP: 
      klass = mkChar("numeric"); 
      break; 
      case SYMSXP: 
      klass = mkChar("name"); 
      break; 
      case LANGSXP: 
      klass = lang2str(obj, t); 
      break; 
      default: 
      klass = type2str(t); 
      } 
     } 
    } 
    else 
     klass = asChar(klass); 
    PROTECT(klass); 
    value = ScalarString(klass); 
    UNPROTECT(1); 
    return value; 
} 

所以,你可以看到它做了一堆檢查,對所有這些案件你得到了NULL

爲你一個簡單的方法是隻是調用class從你的函數:

eval(lang2(install("class"), x), R_GlobalEnv) 
+0

+1感謝EDDI,完美。並感謝* easy *出路! –

+0

你確定這是用於S3對象的函數嗎?它看起來像'R_do_data_class'被用於這些。 'R_data_class'之前有一個註釋,它似乎(對我來說)表示它被用於S4類。 –

+0

@ JoshO'Brien哦,我不知道。我認爲這對我來說是一個很好的起點,可以做更多的研究,但我現在不會接受(對不起eddi!),因爲看起來我的原始問題*可能沒有答案,所以不希望人們忽視它。 –

相關問題