可以通过索引来选取指定的值。创建索引的主要方式有:
正整数索引 可以使用类似 x[i]
和 x[i, j]
的方式提取向量或列表的第 i 个元素,矩阵或数据框的第 i 行第 j 列的元素。i
和 j
可以是整数(可以是双整型,数值为整数即可),也可以是数值向量。当索引为数值向量时,会提取对应行/列的数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 > x <- 1:100 > x[5 ] [1 ] 5 > m <- matrix(x, nrow = 10 ) > m [,1 ] [,2 ] [,3 ] [,4 ] [,5 ] [,6 ] [,7 ] [,8 ] [,9 ] [,10 ] [1 ,] 1 11 21 31 41 51 61 71 81 91 [2 ,] 2 12 22 32 42 52 62 72 82 92 [3 ,] 3 13 23 33 43 53 63 73 83 93 [4 ,] 4 14 24 34 44 54 64 74 84 94 [5 ,] 5 15 25 35 45 55 65 75 85 95 [6 ,] 6 16 26 36 46 56 66 76 86 96 [7 ,] 7 17 27 37 47 57 67 77 87 97 [8 ,] 8 18 28 38 48 58 68 78 88 98 [9 ,] 9 19 29 39 49 59 69 79 89 99 [10 ,] 10 20 30 40 50 60 70 80 90 100 > m[5 , 5 ] [1 ] 45 > m[5 , c (4 ,6 )] [1 ] 35 55
索引使用向量时,对向量中的元素是否重复不做要求,即可以在同一次取值中使用相同的索引值:
1 2 3 4 5 6 > m[5 , c (4 , 5 , 6 )] [1 ] 35 45 55 > m[5 , c (5 , 5 , 5 )] [1 ] 45 45 45 > m[5 , c (6 , 5 , 4 , 5 )] [1 ] 55 45 35 45
R 的索引是从 1 开始的,这一点与 C++ 等语言不同。
对于数据框,如果选取一列或一行数据,生成的对象是向量;但如果是选取多列和多行,生成的对象则是数据框。若想在使用索引取值时取消类型退化(即保持索引的单行或单列对象为数据框而不是向量),可以附加 drop = FALSE
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 > df <- data.frame(a=c (1 ,2 ,3 ),b=c ("a" ,"b" ,"c" ),c =c (TRUE ,FALSE ,TRUE )) > df a b c 1 1 a TRUE 2 2 b FALSE 3 3 c TRUE > df[1 :2 ,1 :2 ] a b 1 1 a2 2 b> class (df[1 :2 ,1 :2 ]) [1 ] "data.frame" > df[1 :2 ,1 ] [1 ] 1 2 > class (df[1 :2 ,1 ]) [1 ] "numeric" > df[1 :2 ,1 ,drop = FALSE ] a 1 1 2 2 > class (df[1 :2 ,1 ,drop = FALSE ]) [1 ] "data.frame"
同样地,对矩阵或数组也有类似现象。
负整数索引 负整数索引的使用方式基本上与正整数索引类似,主要区别在于负整数索引指定的是不选取 的行或列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 > m <- matrix(1 :100 , nrow = 10 ) > m [,1 ] [,2 ] [,3 ] [,4 ] [,5 ] [,6 ] [,7 ] [,8 ] [,9 ] [,10 ] [1 ,] 1 11 21 31 41 51 61 71 81 91 [2 ,] 2 12 22 32 42 52 62 72 82 92 [3 ,] 3 13 23 33 43 53 63 73 83 93 [4 ,] 4 14 24 34 44 54 64 74 84 94 [5 ,] 5 15 25 35 45 55 65 75 85 95 [6 ,] 6 16 26 36 46 56 66 76 86 96 [7 ,] 7 17 27 37 47 57 67 77 87 97 [8 ,] 8 18 28 38 48 58 68 78 88 98 [9 ,] 9 19 29 39 49 59 69 79 89 99 [10 ,] 10 20 30 40 50 60 70 80 90 100 > m[-c (1 :4 ,6 :10 ), 4 :6 ] [1 ] 35 45 55
可以在不同的索引位置上使用正负不同的索引,但处于同一位置的索引正负必须相同:
1 2 3 4 > m[c (5 ,-5 ), 5 ] Error in m[c (5 , -5 ), 5 ] : only 0 's may be mixed with negative subscripts > m[c(4,-6), 5] Error in m[c(4, -6), 5] : only 0' s may be mixed with negative subscripts
零索引 使用数字 0 作索引本身并不会引起错误或警告,但因为返回的值不是数字 0 就是空对象,一般没有实际应用价值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 > m <- matrix(1 :100 , nrow = 10 ) > m [,1 ] [,2 ] [,3 ] [,4 ] [,5 ] [,6 ] [,7 ] [,8 ] [,9 ] [,10 ] [1 ,] 1 11 21 31 41 51 61 71 81 91 [2 ,] 2 12 22 32 42 52 62 72 82 92 [3 ,] 3 13 23 33 43 53 63 73 83 93 [4 ,] 4 14 24 34 44 54 64 74 84 94 [5 ,] 5 15 25 35 45 55 65 75 85 95 [6 ,] 6 16 26 36 46 56 66 76 86 96 [7 ,] 7 17 27 37 47 57 67 77 87 97 [8 ,] 8 18 28 38 48 58 68 78 88 98 [9 ,] 9 19 29 39 49 59 69 79 89 99 [10 ,] 10 20 30 40 50 60 70 80 90 100 > m[0 , 5 ] integer(0 ) > m[5 , 0 ] integer(0 ) > m[0 , 0 ] <0 x 0 matrix>
空格索引 对于二维数据 x
,x[i]
和 x[i,]
是有差别的,前者是指按列读取数据的第 i 个元素,后者是指第 i 行的全部元素:
1 2 3 4 5 6 7 8 9 > m <- matrix(1 :100 , nrow = 10 ) > m[5 ] [1 ] 5 > m[15 ] [1 ] 15 > m[5 ,] [1 ] 5 15 25 35 45 55 65 75 85 95 > m[,5 ] [1 ] 41 42 43 44 45 46 47 48 49 50
该方法在 R 中被称为空格索引。
逻辑值索引 可以使用逻辑值向量作为索引来控制行或列的选取或非选取:
1 2 3 4 5 6 7 8 > x <- 1:10 > m <- matrix(1 :100 , nrow = 10 ) > x[c (T , F , T , F , T , T , F , F , F , T )] [1 ] 1 3 5 6 10 > m[5 , c (F , F , F , T , T , T , F , F , F , F )] [1 ] 35 45 55 > m[c (F , F , F , T , T , T , F , F , F , F ), 5 ] [1 ] 44 45 46
名称索引 如果对象具有名称属性,就可以使用对应的名称作为索引值来提取数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 > df <- data.frame(value=c (1 , 10 , 100 ),char=c ("a" ,"b" ,"c" ),status=c (TRUE ,FALSE ,TRUE )) > df value char status 1 1 a TRUE 2 10 b FALSE 3 100 c TRUE > df[,"char" ] [1 ] "a" "b" "c" > df[1 :2 ,"char" ] [1 ] "a" "b" > df[3 ,c ("value" , "char" )] value char 3 100 c
除了上述的记号之外,$
和 [[]]
也可用于某些特定的对象。
$
可以用于提取数据框或列表对象中的值,例如:
1 2 3 4 5 6 7 8 9 10 11 12 > df <- data.frame(value=c (1 , 10 , 100 ),char=c ("a" ,"b" ,"c" ),status=c (TRUE ,FALSE ,TRUE )) > df value char status 1 1 a TRUE 2 10 b FALSE 3 100 c TRUE > df$value [1 ] 1 10 100 > df$char [1 ] "a" "b" "c" > df$status [1 ] TRUE FALSE TRUE
这种方法会返回一个向量。同样地,对于列表也是如此:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 > lst <- list (value=c (1 , 10 , 100 ),char=c ("a" ,"b" ,"c" ),status=c (TRUE ,FALSE ,TRUE )) > lst $value [1 ] 1 10 100 $char [1 ] "a" "b" "c" $status [1 ] TRUE FALSE TRUE > lst$value [1 ] 1 10 100 > lst$char [1 ] "a" "b" "c" > lst$status [1 ] TRUE FALSE TRUE
使用单中括号 []
索引会有许多限制,例如对上面的 lst
对象采取以下操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 > lst$value [1 ] 1 10 100 > lst[1 ] $value [1 ] 1 10 100 > class (lst$value) [1 ] "numeric" > class (lst[1 ]) [1 ] "list" > sum (lst$value) [1 ] 111 > sum (lst[1 ]) Error in sum (lst[1 ]) : invalid 'type' (list ) of argument
可以看出,使用单中括号索引列表得到的是仍是列表,即使只有一个元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 > lst <- list (value=1 ,char=c ("a" ,"b" ,"c" ),status=c (TRUE ,FALSE ,TRUE )) > lst $value [1 ] 1 $char [1 ] "a" "b" "c" $status [1 ] TRUE FALSE TRUE > class (lst$value) [1 ] "numeric" > class (lst[1 ]) [1 ] "list"
因此,对于列表中不含名称的元素(或不想使用名称),可以使用双中括号 [[]]
来提取数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 > lst <- list (value=c (1 , 10 , 100 ),char=c ("a" ,"b" ,"c" ),status=c (TRUE ,FALSE ,TRUE )) > lst $value [1 ] 1 10 100 $char [1 ] "a" "b" "c" $status [1 ] TRUE FALSE TRUE > lst[1 ] $value [1 ] 1 10 100 > lst[[1 ]] [1 ] 1 10 100 > class (lst[1 ]) [1 ] "list" > class (lst[[1 ]]) [1 ] "numeric"
同样地,对于名称索引,也有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 > lst $value [1 ] 1 10 100 $char [1 ] "a" "b" "c" $status [1 ] TRUE FALSE TRUE > lst["char" ] $char [1 ] "a" "b" "c" > lst[["char" ]] [1 ] "a" "b" "c" > class (lst["char" ]) [1 ] "list" > class (lst[["char" ]]) [1 ] "character"