为什么向量的类是向量元素的类而不是向量本身?

meg*_*ger 9 r

我不明白为什么向量的类是向量元素的类而不是向量本身.

vector <- c("la", "la", "la")
class(vector) 
## [1] "character"

matrix <- matrix(1:6, ncol=3, nrow=2)
class(matrix) 
## [1] "matrix"
Run Code Online (Sandbox Code Playgroud)

Dav*_*urg 8

这就是我从中得到的.class主要用于面向对象的编程,R中还有其他函数可以为你提供对象的存储模式(参见?typeof?mode).

看着 ?class

许多R对象都有一个class属性,一个字符向量给出了对象继承的类的名称.如果对象没有class属性,则它有一个隐式类,"matrix","array"或mode(x)的结果

它似乎class工作如下

  1. 它首先查找$class属性

  2. 如果没有,它通过检查属性(在a中不存在)来检查对象是否matrix具有array结构或结构$dimvector

    2.1.如果$dim包含两个条目,则将其称为amatrix

    2.2.如果$dim包含一个条目或两个以上的条目,它将称之为array

    2.3.如果$dim长度为0,则进入下一步(mode)

  3. 如果$dim长度为0并且没有$class属性,则执行mode

所以根据你的例子

mat <- matrix(rep("la", 3), ncol=1)
vec <- rep("la", 3)
attributes(vec)
# NULL
attributes(mat)
## $dim
## [1] 3 1
Run Code Online (Sandbox Code Playgroud)

所以你可以看到它vec不包含任何属性(参见?c?as.vector解释)

所以在第一种情况下,class执行

attributes(vec)$class
# NULL
length(attributes(vec)$dim)
# 0
mode(vec)
## [1] "character"
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,它检查

attributes(mat)$class
# NULL
length(attributes(mat)$dim)
##[1] 2
Run Code Online (Sandbox Code Playgroud)

它看到该对象有两个维度,并在那里调用它 matrix

为了说明两者vecmat具有相同的存储模式,您可以这样做

mode(vec)
## [1] "character"
mode(mat)
## [1] "character"
Run Code Online (Sandbox Code Playgroud)

例如,您还可以看到与数组相同的行为

ar <- array(rep("la", 3), c(3, 1)) # two dimensional array
class(ar)
##[1] "matrix"
ar <- array(rep("la", 3), c(3, 1, 1)) # three dimensional array
class(ar)
##[1] "array"
Run Code Online (Sandbox Code Playgroud)

因此,无论arraymatrix不解析class属性.让我们检查一下,例如,做什么data.frame.

df <- data.frame(A = rep("la", 3))
class(df)
## [1] "data.frame"
Run Code Online (Sandbox Code Playgroud)

从哪里class拿走了它?

attributes(df)    
# $names
# [1] "A"
# 
# $row.names
# [1] 1 2 3
# 
# $class
# [1] "data.frame"
Run Code Online (Sandbox Code Playgroud)

如您所见,data.fram设置$class属性,但这可以更改

attributes(df)$class <- NULL
class(df)
## [1] "list"
Run Code Online (Sandbox Code Playgroud)

为什么list?因为data.frame没有$dim属性(既不是$class一个,因为我们只是删除了它),因此class执行mode(df)

mode(df)
## [1] "list"
Run Code Online (Sandbox Code Playgroud)

最后,为了说明如何class工作,我们可以手动设置class我们想要的任何东西,看看它会给我们什么

mat <- structure(mat, class = "vector")
vec <- structure(vec, class = "vector")
class(mat)
## [1] "vector"
class(vec)
## [1] "vector"
Run Code Online (Sandbox Code Playgroud)


Sim*_*lon 6

R需要知道您正在操作的对象的类,以便对该对象执行适当的方法调度.R中的原子数据类型是一个向量,没有标量这样的东西,即R认为单个整数是一个长度为一个向量; is.vector( 1L ).

为了分派正确的方法,R必须知道数据类型.当你的语言被隐式地矢量化并且一切都被设计为在向量上运行时,知道某些东西是一个向量并不是很多.

is.vector( list( NULL , NULL ) )
is.vector( NA )
is.vector( "a" )
is.vector( c( 1.0556 , 2L ) )
Run Code Online (Sandbox Code Playgroud)

所以,你可以采取的返回值class( 1L )[1] "integer"要的意思是,我是由类型的原子向量integer.

尽管在引擎盖下a matrix实际上只是一个具有两个维度属性的向量,但R必须知道它是一个矩阵,因此它可以在矩阵的元素上逐行或逐列操作(或单独在任何单个下标上操作)元件).在子集化之后,您将返回矩阵中元素的数据类型的向量,这将允许R为您的数据调度适当的方法(例如,sort对字符向量或数字向量执行);

/* from the underlying C code in /src/main/subset.c....*/
result = allocVector(TYPEOF(x), (R_xlen_t) nrs * (R_xlen_t) ncs)
Run Code Online (Sandbox Code Playgroud)

您还应该注意,在确定对象的类之前,R将始终检查它是第一个向量,例如,is.matrix(x)在某个矩阵上运行的情况下x,R检查它是否是第一个向量,然后检查对于维度属性.如果维度属性是INTEGER数据类型为LENGTH2 的向量,则它满足该对象作为矩阵的条件(以下代码片段来自/ src/include /的Rinlinedfuns.h)

INLINE_FUN Rboolean isMatrix(SEXP s)
  495 {
  496     SEXP t;
  497     if (isVector(s)) {
  498    t = getAttrib(s, R_DimSymbol);
  499    /* You are not supposed to be able to assign a non-integer dim,
  500       although this might be possible by misuse of ATTRIB. */
  501    if (TYPEOF(t) == INTSXP && LENGTH(t) == 2)
  502        return TRUE;
  503     }
  504     return FALSE;
  505 }

#  e.g. create an array with height and width....  
a <- array( 1:4 , dim=c(2,2) )

#  this is a matrix!
class(a)
#[1] "matrix"

# And the class of the first column is an atomic vector of type integer....
class(a[,1])
[1] "integer"
Run Code Online (Sandbox Code Playgroud)

  • 是的,这很棒.很好,你提出/强调"字符"(例如)真正意味着"字符*矢量*"的事实.也很好地解释为什么矩阵值得他们自己的班级. (2认同)

pai*_*nco 4

R语言定义中,向量有六种基本类型,其中之一是"character". 实际上并不存在基本的“向量”类型,而是有六种不同类型的向量,它们都是基本类型。

另一方面,矩阵是一种数据结构。