R语言入门与实践
上QQ阅读APP看书,第一时间看更新

3.2 属性

属性是附加给原子型向量的额外信息,可以将属性赋予一个原子型向量(或者任意一个R对象)。属性并不会影响这个对象的取值,在显示该对象时也不会出现属性信息。你可以把属性理解为对象的元数据(metadata),它的作用是将与这个对象相关的信息以一种便捷的形式存起来并附加给该对象。通常来说,R会选择忽略这些元数据信息,但某些R函数会检查对象是否附有某些特定的属性值。这些函数会根据该数据对象的特定属性信息决定是否进行某些特定的操作。

用attributes函数可以查看一个对象包含哪些属性信息。如果一个对象没有任何属性信息,attributes会返回结果NULL,即空值。像die这样的原子型向量,除非人为地加上一些属性,否则它不附带任何属性值。

        attributes(die)
        ## NULL

NULL

R用NULL来表示空值,意即没有任何信息。某些R函数会返回NULL值,因为它们没有明确定义返回值。你也可以自己生成一个NULL对象,只需要键入NULL即可,记得全是大写字母。

3.2.1 名称属性

一个原子型向量最常见的三种属性是:名称(name)、维度(dim)和(class)。每种属性都有自己的辅助函数,以将相应的属性附加给某个R对象。对于某些附有属性的R对象,还可以使用这些辅助函数查询它们所包含的属性具体是什么。例如,可以用辅助函数names查询die对象的名称属性。

        names(die)
        ## NULL

返回值为NULL表明die对象没有名称属性。利用辅助函数,可以将一串字符向量赋给die对象,作为它的名称属性值。这个字符向量的长度应该与die等长,每个字符元素都对应die中相应位置元素的名称。

        names(die) <- c("one", "two", "three", "four", "five", "six")

现在,die对象就具有了名称属性。

        names(die)
        ## "one"   "two"   "three" "four"  "five"  "six"

        attributes(die)
        ## $names
        ## [1] "one"   "two"   "three" "four"  "five"  "six"

当显示die向量时,名称属性值会显示在对应元素的上方,如下所示。

        die
        ##  one   two three  four  five   six
        ##    1     2     3     4     5     6

然而,名称属性值并不会对向量中的实际值产生影响,即便是改变了向量中元素的取值,名称属性值也不会改变。

        die + 1
        ##  one   two three  four  five   six
        ##    2     3     4     5     6     7

可以使用names函数批量修改或者删除某个对象的名称属性。要更改名称属性,只要将新的名称赋给names函数即可。

        names(die) <- c("uno", "dos", "tres", "quatro", "cinco", "seis")
        die
        ##  uno    dos   tres quatro  cinco   seis
        ##    1      2      3      4      5      6

要想一次性删除名称属性值,需要将NULL赋给names函数。

        names(die) <- NULL
        die
        ##  1 2 3 4 5 6

3.2.2 维度属性

原子型向量可以转换成一个n数组(array),方法是用dim函数将相应的维度属性赋给该向量。具体来说,就是把这个向量的dim属性设定为n。R会将该向量中的元素重新排列到n维。每一个维度上可以包含的行数(或者列数,等等)至多等于这个向量的第n个元素。比如说,可以将向量die重新组织成一个2×3的矩阵(含有两行三列)。

        dim(die) <- c(2, 3)
        die
        ##      [,1] [,2] [,3]
        ## [1, ]    1    3    5
        ## [2, ]    2    4    6

或者将其重新组织成一个3×2的矩阵(含有三行两列),如下所示。

        dim(die) <- c(3, 2)
        die
        ##      [,1] [,2]
        ## [1, ]    1    4
        ## [2, ]    2    5
        ## [3, ]    3    6或者将其重新组织成一个1×2×3的超立方体(其中含有一行、两列和三个切片)。这样的数据结构是三维的,但在二维的计算机屏幕上展示时,R需要一个切片一个切片地展示,如下所示。
        dim(die) <- c(1, 2, 3)
        die
        ## , , 1
        ##
        ##      [,1] [,2]
        ## [1, ]    1    2
        ##
        ## , , 2
        ##
        ##      [,1] [,2]
        ## [1, ]    3    4
        ##
        ## , , 3
        ##
        ##      [,1] [,2]
        ## [1, ]    5    6

在分配维度属性时,R始终将第一个值赋给行数,将第二个值赋给列数。总的来说,R对行列进行维度操作时,行的优先权要高于列。

你也许注意到了,R在将元素重新排列到不同的行和列时,我们能干涉的程度很小。比如说,R会先将矩阵的第一列排满,再跳到第二列进行排列。这样的重新排列是以列为优先顺序的,而不是以行。如果想人为控制这样的排列过程,可以使用辅助函数matrix或array。它们实现的功能与dim一样,但包含一些额外的参数,用于控制上述过程。