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

R 为什么向量的类是向量元素的类而不是向量本身?,r,R,我不明白为什么向量的类是向量元素的类而不是向量本身 vector <- c("la", "la", "la") class(vector) ## [1] "character" matrix <- matrix(1:6, ncol=3, nrow=2) class(matrix) ## [1] "matrix" 矢量在中,矢量有六种基本类型,其中一种是“字符”。实际上没有基本的“向量”类型,而是六种不同类型的向量,它们都是基本类型 另一方面,是一种数据结构。R需要知道正在操作

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

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

matrix <- matrix(1:6, ncol=3, nrow=2)
class(matrix) 
## [1] "matrix"
矢量在中,矢量有六种基本类型,其中一种是
“字符”
。实际上没有基本的“向量”类型,而是六种不同类型的向量,它们都是基本类型


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

R需要知道正在操作的对象的类,以便对该对象执行适当的方法分派。R中的原子数据类型是向量,没有标量,即R将单个整数视为长度为一个向量<代码>是.vector(1L)

为了分派正确的方法,R必须知道数据类型。当你的语言是隐式向量化的,并且所有的东西都被设计为在向量上运行时,知道某些东西是向量并没有多大用处

is.vector( list( NULL , NULL ) )
is.vector( NA )
is.vector( "a" )
is.vector( c( 1.0556 , 2L ) )
所以你可以取
类(1L)
的返回值,它是
[1]“integer”
,意思是,我是一个由类型
integer
组成的原子向量

尽管事实上a
矩阵实际上只是一个具有二维属性的向量,但R必须知道它是一个矩阵,以便它可以对矩阵的元素(或单个下标元素)进行行或列操作。子集设置后,您将返回矩阵中元素的数据类型向量,这将允许R为您的数据分派适当的方法(例如,对字符向量或数字向量执行
排序

/*来自/src/main/subset.C中的底层C代码*/
结果=allocVector(类型(x),(R_xlen_t)nrs*(R_xlen_t)ncs)
您还应该注意,在确定对象的类别之前,R将始终检查它是否是第一个向量,例如,在某些矩阵上运行
is.matrix(x)
时,
x
,R检查它是否是第一个向量,然后检查维度属性。如果维度属性是
INTEGER
数据类型为
LENGTH
2的向量,则满足该对象为矩阵的条件(以下代码段来自/src/include/)中的Rinlinedfuns.h)

INLINE\u-FUN-boroan-isMatrix(SEXP-s)
495 {
496个SEXP-t;
497如果(isVector){
498 t=getAttrib(s,R_DimSymbol);
499/*您不能分配非整数dim,
500,但这可能是由于滥用ATTRIB造成的*/
501如果(类型(t)=INTSXP和长度(t)==2)
502返回TRUE;
503     }
504返回错误;
505 }
#例如,创建一个具有高度和宽度的数组。。。。

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

查看
?类时

许多R对象都有一个class属性,一个字符向量给出 对象从中继承的类的名称。如果对象 没有class属性,它有一个隐式类“matrix”, “数组”或模式(x)的结果

似乎
class
的工作原理如下

  • 它首先查找
    $class
    属性

  • 如果没有,它通过检查
    $dim
    属性(在
    向量中不存在)来检查对象是否具有
    矩阵
    数组
    结构

    2.1。如果
    $dim
    包含两个条目,它将称之为
    矩阵

    2.2。如果
    $dim
    包含一个条目或两个以上条目,它将称之为
    数组

    2.3。如果
    $dim
    的长度为0,则转到下一步(
    模式

  • 如果
    $dim
    的长度为0,并且没有
    $class
    属性,它将执行
    模式
  • 根据你的例子

    mat <- matrix(rep("la", 3), ncol=1)
    vec <- rep("la", 3)
    attributes(vec)
    # NULL
    attributes(mat)
    ## $dim
    ## [1] 3 1
    
    在第二种情况下,它检查

    attributes(mat)$class
    # NULL
    length(attributes(mat)$dim)
    ##[1] 2
    
    它看到该对象有两个维度,因此调用它
    matrix

    为了说明
    vec
    mat
    具有相同的存储模式,您可以

    mode(vec)
    ## [1] "character"
    mode(mat)
    ## [1] "character"
    
    例如,您还可以看到数组的相同行为

    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"
    
    class
    从哪里取的

    attributes(df)    
    # $names
    # [1] "A"
    # 
    # $row.names
    # [1] 1 2 3
    # 
    # $class
    # [1] "data.frame"
    
    如您所见,
    data.fram
    设置了一个
    $class
    属性,但这是可以更改的

    attributes(df)$class <- NULL
    class(df)
    ## [1] "list"
    
    最后,为了说明
    的工作原理,我们可以手动将
    设置为我们想要的,并查看它会给我们什么

    mat <- structure(mat, class = "vector")
    vec <- structure(vec, class = "vector")
    class(mat)
    ## [1] "vector"
    class(vec)
    ## [1] "vector"
    

    mat这是我找到的最好的图表,它列出了
    class
    函数使用的类层次结构:

    虽然类名与R
    class
    函数的结果并不完全一致,但我相信层次结构基本上是准确的。答案的关键是
    函数只给出层次结构中的根类


    您将看到
    Vector
    不是根类。您的示例的根类是
    StrVector
    ,它对应于
    “character”
    类,该类表示包含字符元素的向量。相反,
    Matrix
    本身就是一个根类;因此,它的类是
    “matrix”

    您的“vector”仍然是形式类
    vector
    。它被认为是一个字符向量。参见
    is.vector(vector)
    ?vector
    @RichardScriven,我认为这里的实际问题是
    为什么会像他那样行事,也就是说,为什么它会为
    矩阵
    中包含任何类型的向量返回“矩阵”,而当
    向量
    格式中存储的数据发生错误时,它会返回向量的实际类。有人解释说是的
    attributes(df)$class <- NULL
    class(df)
    ## [1] "list"
    
    mode(df)
    ## [1] "list"
    
    mat <- structure(mat, class = "vector")
    vec <- structure(vec, class = "vector")
    class(mat)
    ## [1] "vector"
    class(vec)
    ## [1] "vector"