跳至內容

R/R對象屬性的函數小結

維基教科書,自由的教學讀本
< R

R對象屬性的函數小結

[編輯]

任何程式語言都會包含有兩個最基本的概念:數據類型和數據結構 數據類型指的是數值、字符串、邏輯值及他們衍生出的各種複合類型 數據結構描述各種數據類型所組成的對象是如何組織的

數據類型和數據結構包含兩個層次:物理層次和邏輯層次

  • 類似於硬盤分區中的物理分區和邏輯分區的區別,對於一塊硬盤,可以用磁盤管理工具可以分成多個分區來儲存數據,這些分區被稱為邏輯分區;但無論我們分成多少分區,他們都同屬於一個物理分區
  • 物理層次:計算機物理內存上是如何存儲的數據類型和結構
  • 邏輯層次:不同程式語言本身定義的基本數據類型和結構,以及用戶自定義的各種數據類型,這是高級程式語言對底層計算機物理儲存的一種高級封裝,使得程式語言更加接近於自然語言。
  • 在面向對象的編程中,被封裝成各種類和對象。

查看數據類型class、mode和typeof

[編輯]

R的許多語法都是繼承自S語言,R語言的開發時間也比較早,許多現在的程序概念在當時並沒有被提出。 mode和storage.mode函數描述早期程序的數據類型,繼承自S語言,更接近與內存儲存的數據類型,storage.mode的描述更準確一些。mode和storage.mode的返回值基於typeof函數的結果。 typeof函數描述最新的、更準確的數據類型,其返回值的結果和storage.mode一樣,在進行程序編譯時比較重要。 class函數描述的是R語言定義的類屬性,如向量、列表、數據框等,可以由用戶自定義。類是面向對象編程中的概念,如Biostrings包中定義的一個DNAstring類。 總結:mode、storage.mode和typeof描述的數據類型存儲的物理屬性,對象所儲存的數據類型改變時發生改變;class描述的是數據的存儲的邏輯層次屬性,默認與物理屬性相同,可以由用戶自定義修改,但不影響對象所儲存的實際數據類型。

> x<- 1
> mode(x)
[1] "numeric"
> class(x)
[1] "numeric"
> typeof(x)
[1] "double"
> class(x)<- "subclass"
> class(x)
[1] "subclass"
> mode(x)
[1] "numeric"
> typeof(x)
[1] "double"
# 如果用户修改的名称是R的内置数据类型名称,则数据类型发生改变
> class(x) <- "character"
> x
[1] "1"
> class(x)
[1] "character"
> mode(x)
[1] "character"
> typeof(x)
[1] "character"

比較不同R對象的屬性函數返回值的比較

library(methods)
library(dplyr)
library(xml2)
library(Biostrings)

setClass("dummy", representation(x="numeric", y="numeric"))

types <- list(
  "logical vector" = logical(),
  "integer vector" = integer(),
  "numeric vector" = numeric(),
  "complex vector" = complex(),
  "character vector" = character(),
  "raw vector" = raw(),
  factor = factor(),
  "logical matrix" = matrix(logical()),
  "numeric matrix" = matrix(numeric()),
  "logical array" = array(logical(8), c(2, 2, 2)),
  "numeric array" = array(numeric(8), c(2, 2, 2)),
  list = list(),
  pairlist = .Options,
  "data frame" = data.frame(),
  "closure function" = identity,
  "builtin function" = `+`,
  "special function" = `if`,
  environment = new.env(),
  null = NULL,
  formula = y ~ x,
  expression = expression(),
  call = call("identity"),
  name = as.name("x"),
  "paren in expression" = expression((1))[[1]],
  "brace in expression" = expression({1})[[1]],
  "S3 lm object" = lm(dist ~ speed, cars),
  "S4 dummy object" = new("dummy", x = 1:10, y = rnorm(10)),
  "external pointer" = read_xml("<foo><bar /></foo>")$node,
  "DNAString" = DNAString(),
  "RNAString" = RNAString(),
  "AAString" = AAString()
)

type_info <- Map(
  function(x, nm)
  {
    tibble(
      "spoken type" = nm,
      class = class(x),
      mode  = mode(x),
      typeof = typeof(x),
      storage.mode = storage.mode(x)
    )
  },
  types,
  names(types)
) %>% bind_rows

knitr::kable(type_info)

輸出:

|spoken type         |class       |mode        |typeof      |storage.mode |
|:-------------------|:-----------|:-----------|:-----------|:------------|
|logical vector      |logical     |logical     |logical     |logical      |
|integer vector      |integer     |numeric     |integer     |integer      |
|numeric vector      |numeric     |numeric     |double      |double       |
|complex vector      |complex     |complex     |complex     |complex      |
|character vector    |character   |character   |character   |character    |
|raw vector          |raw         |raw         |raw         |raw          |
|factor              |factor      |numeric     |integer     |integer      |
|logical matrix      |matrix      |logical     |logical     |logical      |
|numeric matrix      |matrix      |numeric     |double      |double       |
|logical array       |array       |logical     |logical     |logical      |
|numeric array       |array       |numeric     |double      |double       |
|list                |list        |list        |list        |list         |
|pairlist            |pairlist    |pairlist    |pairlist    |pairlist     |
|data frame          |data.frame  |list        |list        |list         |
|closure function    |function    |function    |closure     |function     |
|builtin function    |function    |function    |builtin     |function     |
|special function    |function    |function    |special     |function     |
|environment         |environment |environment |environment |environment  |
|null                |NULL        |NULL        |NULL        |NULL         |
|formula             |formula     |call        |language    |language     |
|expression          |expression  |expression  |expression  |expression   |
|call                |call        |call        |language    |language     |
|name                |name        |name        |symbol      |symbol       |
|paren in expression |(           |(           |language    |language     |
|brace in expression |{           |call        |language    |language     |
|S3 lm object        |lm          |list        |list        |list         |
|S4 dummy object     |dummy       |S4          |S4          |S4           |
|external pointer    |externalptr |externalptr |externalptr |externalptr  |
|DNAString           |DNAString   |S4          |S4          |S4           |
|RNAString           |RNAString   |S4          |S4          |S4           |
|AAString            |AAString    |S4          |S4          |S4           |

查看數據結構的函數--str和attributes函數

[編輯]

str和summary函數類似,str是structure的縮寫,主要是查看當前對象的數據結構的描述,無法修改對象的數據結構,當對象儲存的數據結構被修改時,str函數的返回值發生變化。 attributes描述的是R對象邏輯層次的數據結構,可以修改,可以由用戶自定義,修改之後立即生效,但不影響R對象儲存在內存的內容,但會影響對象的數據結構,str的函數返回值會發生改變,mostattributes可以設置更複雜的數據結構。

## 查看R语言内置的数据结构
> x <- cbind(a = 1:3, pi = pi)
> x
     a       pi
[1,] 1 3.141593
[2,] 2 3.141593
[3,] 3 3.141593
# 使用attributes查看对象x的逻辑数据结构
> attributes(x)
$dim
[1] 3 2

$dimnames
$dimnames[[1]]
NULL

$dimnames[[2]]
[1] "a"  "pi"

# 使用str查看对象x的物理数据结构
> str(x)
 num [1:3, 1:2] 1 2 3 3.14 3.14 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "a" "pi"
# 使用attributes修改对象x的数据结构
> attributes(x) <- NULL
> x
[1] 1.000000 2.000000 3.000000 3.141593 3.141593 3.141593
# 修改后,逻辑的数据结构变成NULL
> attributes(x)
NULL
# str函数返回逻辑层级的数据结构消失时,数据在物理储存的数据结构
> str(x)
 num [1:6] 1 2 3 3.14 3.14 ...
# 使用mostattributes函数还原对象x原来的数据结构
> mostattributes(x) <- list(dim = 3:2, dimnames = list(NULL,c("a","pi")), names = paste(1:6))
> x
     a       pi
[1,] 1 3.141593
[2,] 2 3.141593
[3,] 3 3.141593
> attributes(x)
$dim
[1] 3 2

$dimnames
$dimnames[[1]]
NULL

$dimnames[[2]]
[1] "a"  "pi"


> str(x)
 num [1:3, 1:2] 1 2 3 3.14 3.14 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "a" "pi"

# 查看一个函数的数据结构
> str(numeric)
function (length = 0L)

is()及is類函數的簡單講解

[編輯]

is.*()的一類函數可以判斷對象是否是某一種特定的數據類型或數據結構 is()可以查看該對象所屬的所有數據類型或數據結構

> x <- cbind(a = 1:3, pi = pi)
# 使用is.*()类函数判断对象是否属于该数据类型或数据结构,并返回逻辑值
> is.numeric(x)
[1] TRUE
> is.character(x)
[1] FALSE
> is.vector(x)
[1] FALSE
> is.matrix(x)
[1] TRUE
> is.array(x)
[1] TRUE
> is.data.frame(x)
[1] FALSE
# 查看对象x所属的全部类型
> is(x)
[1] "matrix"           "array"            "structure"        "vector"          
[5] "vector_OR_factor"

可以通過編寫一個函數來查看一個對象的數據類型或數據結構

what.is <- function(x, show.all=FALSE) {

  # set the warn option to -1 to temporarily ignore warnings
  op <- options("warn")
  options(warn = -1)
  on.exit(options(op))

  list.fun <- grep(methods(is), pattern = "<-", invert = TRUE, value = TRUE)
  result <- data.frame(test=character(), value=character(), 
                       warning=character(), stringsAsFactors = FALSE)

  # loop over all "is.(...)" functions and store the results
  for(fun in list.fun) {
    res <- try(eval(call(fun,x)),silent=TRUE)
    if(class(res)=="try-error") {
      next() # ignore tests that yield an error
    } else if (length(res)>1) {
      warn <- "*Applies only to the first element of the provided object"
      value <- paste(res,"*",sep="")
    } else {
      warn <- ""
      value <- res
    }
    result[nrow(result)+1,] <- list(fun, value, warn)
  }

  # sort the results
  result <- result[order(result$value,decreasing = TRUE),]
  rownames(result) <- NULL

  if(show.all)
    return(result)
  else
    return(result[which(result$value=="TRUE"),])
}

查看函數的輸出

> what.is(1)
        test value warning
1  is.atomic  TRUE        
2  is.double  TRUE        
3  is.finite  TRUE        
4 is.numeric  TRUE        
5  is.vector  TRUE        
> what.is(x)
        test value warning
2   is.array  TRUE        
3  is.atomic  TRUE        
4  is.double  TRUE        
5  is.matrix  TRUE        
6 is.numeric  TRUE 
> what.is(numeric)
          test value warning
1  is.function  TRUE        
2 is.recursive  TRUE

參考連結

[編輯]