R是一门著名的可用于数据和统计分析的程序语言,本文翻译自R软件官方文档教程《An Introduction to R》,仅供学习和参考。
6 列表和数据框
6.1 列表
在R中,list
(列表)是一个对象,由称为其component
组件的有序对象集合组成。
组件不需要具有相同的类型,例如,列表可以由数值向量、逻辑值、矩阵、复数向量、字符数组、函数各种对象等组成。以下是如何生成一个列表的简单示例:
> Lst <- list(name="Fred", wife="Mary", no.children=3,
+ child.ages=c(4,7,9))
> Lst
$name
[1] "Fred"
$wife
[1] "Mary"
$no.children
[1] 3
$child.ages
[1] 4 7 9
组件总是有编号的,并且可以通过这些编号进行索引。因此,如果Lst
是具有四个组件的列表,则这些组件可以分别称为Lst[[1]]
、Lst[[2]]
、Lst[[3]]
和Lst[[4]]
。此外,如果Lst[[4]]
是一个向量,那么Lst[[4]][1]
是这个向量的第一个元素。
如果Lst
是一个列表,那么函数length(Lst)
给出了它所拥有的(顶级)组件的数量。
列表的组件也可以被命名,在这种情况下,可以通过将组件名称作为字符串来代替双方括号中的数字来索引组件,或者更方便地,通过给出以下形式的表达式来索引组件:
> list_name$component_name
这是一种非常有用的语法,因为如果您忘记了数字,它可以更容易地获得正确的组件。
因此,在上面给出的简单示例中:
Lst$name
与Lst[[1]]
相同,是字符串"Fred"
Lst$wife
与Lst[[2]]
相同,是字符串"Mary"
Lst$child.ages[1]
与Lst[[4]][1]
相同,是数字4
。
此外,还可以把列表组件的名称放入双方括号中进行使用,即Lst[[“name”]]
与Lst$name
相同。当要提取的组件的名称存储在另一个变量中时,这一点尤其有用,如:
> x <- "name"; Lst[[x]]
[1] "Fred"
区分Lst[[1]]
和Lst[1]
是非常重要的。[[…]]
是用于选择单个元素的运算符,而[…]
是一个通用的下标运算符。因此,前者是列表Lst
中的第一个对象,如果它是命名列表,则并不会包括该名称。后者是仅由第一个组件组成的Lst
的一个子列表,如果是命名列表,则名称也将保留到子列表中。
> Lst[[1]]
[1] "Fred"
> Lst[1]
$name
[1] "Fred"
在索引时,部件的名称可以缩写为可以唯一标识它们所需的最小字母数。因此,Lst$coefficients
可以最低限度地指定为Lst$coe
。Lst$covariance
可以被压缩指定为Lst$cov
。
事实上,名称向量和其他任何属性一样,只是列表的一个属性。当然,除了列表之外的其他结构也可以类似地被赋予名称属性。
6.2 创建和修改列表
新的列表可以通过已有的其他对象来创建,需要使用list()
函数。
> Lst <- list(name_1=object_1, ..., name_m=object_m)
上面的代码将object_1
,object_2
,
⋯
\cdots
⋯,object_m
等已有对象作为组件创建了一个新的列表Lst
,组件名分别为name_1
,name_2
,
⋯
\cdots
⋯,name_m
。组件名是可选的,如果没有指定,就只能通过数字来索引对应组件。用于形成列表的组件在形成新列表时会被复制,即原始对象不会受影响。
与任何带下标的对象一样,可以通过指定其他组件来扩展列表。例如
> Lst[5]<-list(matrix=Mat)
6.2.1 拼接列表
当串联函数c()
被赋予列表参数时,其返回结果也是一个列表,其组件由参数列表的组件按顺序连接在一起形成。
> list.ABC <- c(list.A,list.B,list.c)
回想一下,将向量对象作为参数时,串联函数将所有参数向量的元素连接到一个向量中。在这种情况下,将丢弃所有其他属性,例如维数属性。
6.3 数据框
数据框是一个类为data.frame
的列表。对可以转化为数据框的列表有一些限制,即
-
组件必须是向量(数值、字符串或逻辑)、因子、数字矩阵、列表或其他数据框。
-
组件矩阵、列表和数据框为新数据框提供的变量数量与它们分别具有列、元素或变量的数量一样多。
-
组件向量必须都具有相同的长度,组件矩阵必须都有相同的行数。
在大多数情况下,数据框可以被视为具有可能具有不同类型和属性的列的矩阵。它可以以矩阵形式显示,并使用与矩阵类似的索引方式提取其行,列或元素。
6.3.1 创建数据框
满足数据框列(组件)限制的对象可传给函数 data.frame()
形成一个数据框。
> names <- c("张三","李四","王五")
> ages <- c(15,16,17)
> grades <- c(99,94,92)
> students <- data.frame(name=names, age=ages, grade=grades)
> students
name age grade
1 张三 15 99
2 李四 16 94
3 王五 17 92
可以使用函数 as.data.frame()
将其组件符合数据框限制的列表强制转换为数据框。
从头开始构建数据框的最简单方法是使用 read.table()
函数从外部文件读取整个数据框。这将在之后介绍。
6.3.2 attach()和detach()函数
列表组件的 $
表示法,例如 students$name
,并不总是很方便。
一个有用的解决办法,是以某种方式使列表或数据框的组件在其组件名称下作为变量暂时可见,而无需每次都显式引用列表名称。
attach()
函数将“数据对象”(例如列表或数据框)作为其参数。
> attach(students)
上述代码将数据框students
放在搜索路径中的第2位,如果搜索路径的第1位中没有变量 name
、age
或 grade
,则 name
、age
和 grade
可直接作为普通变量被访问。
但此时赋值如
> age <- age+1
不会替换students
的组件age
,而是用搜索路径上位置 1 的工作目录中的另一个变量 age
覆盖它(如果没有新创建)。要对数据框本身进行永久更改,最简单的方法是再次求助于 $
表示法:
> students$age <- age+1
如果要取消这种机制,请使用detach()
函数。更准确地说,detach()
语句会将当前数据框中位于第二位的变量从搜索路径中分离出来。因此,在当前上下文中,变量 name
、age
和 grade
将不再可见,除非在 students$age
等表示方式下。
6.3.3 数据框相关操作
允许您在同一个工作目录中舒适地一起处理许多不同问题的一个有用的技巧是:
- 将与各个问题相关的变量分别收集到数据框中,并给各列取上适当的名称。
- 在处理问题时,在第二位搜索路径中附加适当的数据框,并使用第一位的变量来获取和使用操作量和临时变量。
- 在结束单个问题之前,使用
$
赋值形式添加您希望保留以供将来参考的任何变量到数据框,然后detach()
- 最后从工作目录中删除所有不需要的变量,并尽可能保持干净的剩余临时变量。
通过这种方式,在同一个目录中处理许多问题非常简单,例如,所有这些问题都有名为 x
、y
和 z
的变量。
6.3.4 附加任意列表
attach() 是一个通用函数,它不仅允许将目录和数据框附加到搜索路径,还允许附加其他类的对象。特别是任何类型为list
的对象都可以用相同的方式进行附加:
> attach(any.old.list)
与此对应,detach()
函数也可用于分离以上附加的对象。
6.3.5 管理搜索路径
search()
函数用于显示当前搜索路径,因此是跟踪哪些数据框和列表(和包)已附加和分离的非常有用的方法。
> search()
[1] ".GlobalEnv" "package:stats" "package:graphics"
[4] "package:grDevices" "package:utils" "package:datasets"
[7] "package:methods" "Autoloads" "package:base"
如上所示。其中,.GlobalEnv
表示当前的第一位工作空间。当附加students
数据框后,再次search
():
> attach(students)
> search()
[1] ".GlobalEnv" "students" "package:stats"
[4] "package:graphics" "package:grDevices" "package:utils"
[7] "package:datasets" "package:methods" "Autoloads"
[10] "package:base"
可见,students
被加入了搜索路径。
如果再分离students
:
> detach(students)
> search()
[1] ".GlobalEnv" "package:stats" "package:graphics"
[4] "package:grDevices" "package:utils" "package:datasets"
[7] "package:methods" "Autoloads" "package:base"