Vectors
无论是atomic vector还是list,都属于vector。这两者构成了R最基本的两大类数据结构。Atomic vector与list的区别在于,前者的元素都必须是由同一数据类型组成的,也就是说atomic vector都是同质的,而list中的元素可以是异质的。Atomic在这里的意思,就是说它就如同R中的原子一样,是构成其它数据结构的基础。
除了vector中保存的数据以外,它还有三个属性:typeof() (是什么), length() (有多少元素)和attributes() (有哪些注释数据)。最常用到的attributes就应该是names(),也就是每个元素的名字。
Atomic vector
Atomic vector常见的是由logical, integer, double, 或者character组成,很罕见的是由raw或者complex组成。我们使用c()(combine的首字母)函数来创建长度大于1的atomic vector。
> x <- c(1, 3.5, 5.6)
> i <- c(1L, 2L, 10L) ## L后缀便于R自动识别输入的数字为整型
> b <- c(TRUE, FALSE, T, F) ## 通常而言,在标准的代码书写过程中应该避免使用不完整的缩写T和F。
> ch <- c("who", "am", "I")
在任何时候,c()函数都是可以圈套使用的,但其结果不会产生分层,而全部会展平为一层。比如
> c(1, c(2, 3)) == c(1, 2, 3)
## [1] TRUE TRUE TRUE
示例使用typeof(), length()以及attributes()查看vector的属性。
> a <- 1:3 ## 冒号(:)是seq()函数的缩写, 用于生成序列数
> typeof(a)
## [1] "integer"
> is.integer(a)
## [1] TRUE
> is.numeric(a)
## [1] TRUE
> length(a)
## [1] 3
> attributes(a)
## NULL
> names(a) <- letters[1:3]
> attributes(a)
## $names
## [1] "a" "b" "c"
> names(a)
## [1] "a" "b" "c"
>
> LETTERS ## LETTERS预存了26个大写字母
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q"
## [18] "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
> typeof(LETTERS)
## [1] "character"
> length(LETTERS)
## [1] 26
当不同类型的数据使用c()函数创建atomic vector时,因为atomic vector的元素都必须是同质的,所以系统会依照character, double, integer, logical的顺序对数据类型进行转换。例如:
> c(9, "a", 1.5, FALSE) ##全部转换为character
## [1] "9" "a" "1.5" "FALSE"
> c(9, 1.5, FALSE) ##全部转换为double
## [1] 9.0 1.5 0.0
> c(FALSE, 9) ##全部转换为integer
## [1] 0 9
下面我们来尝试对atomic vector排序。
> a <- c(4, 2, 1, 3)
> b <- sort(a)
> b
## [1] 1 2 3 4
Factor
Factor是R中非常具有特点的一类atomic vector。首先它是atomic vector,所以它的所有元素必须是同质的,准确地讲其基础类型应该是character。但是它又不同于普通的character型atomic vector。它是将相同字符归类后使用特定格式存放的数据。它有levels()方法,可以得到一个factor中所有的水平(去除重复后所有的元素)。它的创建分为三个步骤,1,将输入的数据转换成character型;2,对所有的水平进行排序(可能是指定的排序,或者自然排序),将排序后的水平保存在levels中;3,使用levels中的水平序列号重新编码输入的元素。
> a <- factor(c(2, 1, 5, 10, 5))
> a
## [1] 2 1 5 10 5
## Levels: 1 2 5 10
> levels(a) ## a中保存的所有水平
## [1] "1" "2" "5" "10"
> a[4] ## a的第四个元素
## [1] 10
## Levels: 1 2 5 10
> as.numeric(a) ##强制将a转换成数字
## [1] 2 1 3 4 3
> as.numeric(as.character(a)) ##将a正确地还原为原始数据
## [1] 2 1 5 10 5
>
> b <- factor(letters[c(2, 1, 5, 10, 5)])
> b
## [1] b a e j e
## Levels: a b e j
> levels(b)
## [1] "a" "b" "e" "j"
> b[4]
## [1] j
## Levels: a b e j
> as.numeric(b) ##与之前的强制转换比较,就发现,这里得到的数字只是重新编码后的数字。
## [1] 2 1 3 4 3
> as.character(b)
## [1] "b" "a" "e" "j" "e"
Factor的值必须是levels中包含的值,否值无法对其编码。
> a <- factor(1:4)
> a[4] <- 5 ## 会得到一个警告
## Warning: invalid factor level, NA generated
> a
## [1] 1 2 3 <NA>
## Levels: 1 2 3 4
> ## 正确的做法是先改变其levels,然后再变更其值
> levels(a) <- c(levels(a), 5)
> a[4] <- 5
> a
## [1] 1 2 3 5
## Levels: 1 2 3 4 5
如果想修改factor中所有等于某值的数据为level中不存在的另一数值,应该直接修改其levels。
> a <- factor(c(letters[1:5], letters[5:1]))
> a
## [1] a b c d e e d c b a
## Levels: a b c d e
> a[2] <- "a" ##是level中存在的值,是可以的。
> a
## [1] a a c d e e d c b a
## Levels: a b c d e
> levels(a)[3] <- "z"
> a
## [1] a a z d e e d z b a
## Levels: a b z d e
Factor的出现除了存贮空间的考虑,更主要是它可以被广泛地应用到公式中。这里简单的示例依靠factor的split()函数的应用。split()是将输入的第一个对象按照输入的第二个(强制转换的)factor的水平进行分割。得到的结果将是一个list。
> x <- sample(1:10, 100, replace = TRUE)
> x
## [1] 6 1 4 9 3 9 1 5 7 1 4 2 8 2 9 4 10 8 2 1 10 2 4
## [24] 6 4 8 8 6 5 3 2 3 10 6 1 1 7 5 2 4 1 1 3 2 6 9
## [47] 7 10 3 5 1 1 3 5 7 5 8 10 2 3 8 10 3 6 9 7 2 8 4
## [70] 1 5 2 1 1 1 10 3 10 3 4 7 9 1 3 5 5 5 5 4 10 10 6
## [93] 10 8 8 3 4 1 7 2
> y <- 1:100
> split(y, x)
## $`1`
## [1] 2 7 10 20 35 36 41 42 51 52 70 73 74 75 83 98
##
## $`2`
## [1] 12 14 19 22 31 39 44 59 67 72 100
##
## $`3`
## [1] 5 30 32 43 49 53 60 63 77 79 84 96
##
## $`4`
## [1] 3 11 16 23 25 40 69 80 89 97
##
## $`5`
## [1] 8 29 38 50 54 56 71 85 86 87 88
##
## $`6`
## [1] 1 24 28 34 45 64 92
##
## $`7`
## [1] 9 37 47 55 66 81 99
##
## $`8`
## [1] 13 18 26 27 57 61 68 94 95
##
## $`9`
## [1] 4 6 15 46 65 82
##
## $`10`
## [1] 17 21 33 48 58 62 76 78 90 91 93
List
同属于vector的list也是一维的,但是其元素可以是任何一种vector,当然也就包括了list。可以用目录来类比list。目录下可以存放不同的文件,包括目录,list也是一样的,只不过文件变成了vector。
构建list使用list()函数,对于除了Atomic vectors和list以外的对象或者混合对象时有时候也可以使用c()。
> a <- list(1:3, letters[1:3], c(FALSE, TRUE), c(1, 1))
> str(a)
## List of 4
## $ : int [1:3] 1 2 3
## $ : chr [1:3] "a" "b" "c"
## $ : logi [1:2] FALSE TRUE
## $ : num [1:2] 1 1
> x <- list(list(list()))
> str(x)
## List of 1
## $ :List of 1
## ..$ : list()
> is.recursive(x)
## [1] TRUE
> x <- list(list(1, 2), c(3, 4))
> y <- c(list(1, 2), c(3, 4)) # y会是一个展平为一层的list
> str(x)
## List of 2
## $ :List of 2
## ..$ : num 1
## ..$ : num 2
## $ : num [1:2] 3 4
> str(y)
## List of 4
## $ : num 1
## $ : num 2
## $ : num 3
## $ : num 4
> a <- c(1:3, letters[1:3], c(FALSE, TRUE), list(1, 1))
> str(a)
## List of 10
## $ : int 1
## $ : int 2
## $ : int 3
## $ : chr "a"
## $ : chr "b"
## $ : chr "c"
## $ : logi FALSE
## $ : logi TRUE
## $ : num 1
## $ : num 1
有些时候,我们也可以视list为二维,甚至多维数据。这取决于读者的理解。从本质上看,list是一种有长度的链表数据,每一个元素其实都是一个指针,它可以指向任何一种数据结构。从这个意义上来讲,它又是同质的。
List与atomic vector的区别与联系
Atomic vector和list一样都可以使用索引号或者名称来访问其元素,但方法会略有不同。
> a <- list(num = 8, alphabet = letters[1:3], logi = TRUE, num = c(1, 1))
> a[[1]]
## [1] 8
> a[1]
## $num
## [1] 8
> is.atomic(a[1])
## [1] FALSE
> is.atomic(a[[1]])
## [1] TRUE
> is.list(a[1])
## [1] TRUE
> names(a)
## [1] "num" "alphabet" "logi" "num"
> a[["alphabet"]]
## [1] "a" "b" "c"
> a["alphabet"] ## 注意[与[[的不同
## $alphabet
## [1] "a" "b" "c"
> a$alphabet
## [1] "a" "b" "c"
> b <- letters[1:8]
> names(b) <- LETTERS[1:8]
> is.atomic(b)
## [1] TRUE
> names(b)
## [1] "A" "B" "C" "D" "E" "F" "G" "H"
> b["C"]
## C
## "c"
> b$C ## 会得到一个错误
## Error: $ operator is invalid for atomic vectors
从上面的例子可以看出,atomic vector可以是list的元素,这也是它为什么可atomic的原因。list访问元素的方式为'[['或者'$',取子集的方式为'[';atomic vector访问元素和取子集的方式均为'['。list和atomic vector都可以通过索引号和名称访问其元素。
如果想去除atomic vector中的某些元素,可以使用'-'号;如果想去除list中的某些元素,可以使用'-'号或者赋值为NULL。也可以使用TRUE/FALSE来取舍。
> a <- 1:4
> a[-c(1, 4)]
## [1] 2 3
> a[2] <- NULL ## 会得到一个错误
## Error: replacement has length zero
> a[c(TRUE, FALSE, TRUE, FALSE)]
## [1] 1 3
> a <- as.list(a)
> a
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 3
##
## [[4]]
## [1] 4
> a[-c(1, 3)]
## [[1]]
## [1] 2
##
## [[2]]
## [1] 4
> a[[-3]] ## 会得到一个错误
## Error: attempt to select more than one element
> a[[3]] <- NULL
> a
## [[1]]
## [1] 1
##
## [[2]]
## [1] 2
##
## [[3]]
## [1] 4
> a[c(TRUE, FALSE, TRUE)]
## [[1]]
## [1] 1
##
## [[2]]
## [1] 4
老师,您好,刚看到您讲的vector这里;我试着
a<-c(1,2,3)
typeof(a) 得到的类型却是double,class(a) 类型则是numeric,为什么不是integer,请老师解答。
你可以试一下a <- c(1L, 2L, 3L)
嗯,在rstudio里试了一下,确实可以了,在网上也找到了一篇博客,专门提到了这个问题,供大家参考:http://blog.sina.com.cn/s/blog_b37ea00701018uwo.html