R语言学习5-向量子集
在本课程中,我们将了解如何根据指定的条件从向量中提取元素。
例如,我们可能只对向量的前20
个元素感兴趣,或者仅对非NA
的元素感兴趣,或者对正数或与感兴趣的特定变量相对应的那些元素感兴趣。
现在有这么一个向量x
,里面包含20
个服从标准正态分布的数字和20
个NA
。
> x
[1] NA NA NA -0.05108979 NA -0.02086817 -0.65883869 NA -0.76755803 -0.94629711 NA
[12] NA 0.25171708 0.18031701 -0.37318508 -0.98855340 -1.68402326 NA NA NA -0.99748631 NA
[23] NA NA NA -0.21191859 NA 0.61580651 0.15191893 -0.84210911 NA NA NA
[34] -0.02113655 NA NA 0.03523937 1.77489019 -0.16145833 -1.51209270
在R
中,想从向量里选择某些特定元素(即“子集”)的方式是,将“索引向量”放在向量名称后方括号中。比如x[1:10]
,就可以获得x
向量的前10
个元素。
> x[1:10]
[1] NA NA NA -0.05108979 NA -0.02086817 -0.65883869 NA -0.76755803 -0.94629711
索引向量有4
种不同的形式-逻辑向量,正整数向量,负整数向量和字符串向量-我们将在本课程中分别介绍。
逻辑索引
让我们首先从逻辑向量开始。处理实际数据时,一种常见的情况是我们要提取向量中非NA
的所有元素。回想一下上一节[1]中的is.na()
函数,返回的是与向量x
长度相同的逻辑向量,其中TRUES
代表x
中的NA
值,FALSE
代表非NA
值。
那么x[is.na(x)]
会返回什么结果?
> x[is.na(x)]
[1] NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
我们可以看到,返回的全部是NA
,正好与实际需求相反。这个时候,只要使用!
进行取反操作就好了。
> y <- x[!is.na(x)]
> y
[1] -0.05108979 -0.02086817 -0.65883869 -0.76755803 -0.94629711 0.25171708 0.18031701 -0.37318508 -0.98855340 -1.68402326 -0.99748631
[12] -0.21191859 0.61580651 0.15191893 -0.84210911 -0.02113655 0.03523937 1.77489019 -0.16145833 -1.51209270
返回的是我们一开始需求单。上述代码已经把结果赋值给了y
,接下来还可以更具条件对y
进行子集提取操作。比如y[y > 0]
> y[y > 0]
[1] 0.25171708 0.18031701 0.61580651 0.15191893 0.03523937 1.77489019
那我们为什么不一开始就使用x[x > 0]
呢?让我们先看看x[x > 0]
的结果。
> x[x > 0]
[1] NA NA NA NA NA NA NA 0.25171708 0.18031701 NA NA NA
[13] NA NA NA NA NA 0.61580651 0.15191893 NA NA NA NA NA
[25] 0.03523937 1.77489019
结果里会出现很多NA
,这是为什么?还记得上一节提过的NA
的实际意义吗?NA
不代表真正的值,而仅仅是一个无意义的占位符。所以NA > 0
也是无意思的,R
只能原样返回NA
。
将逻辑运算符与子集提取相结合,我们可以这样得到x
中的正数。
> x[!is.na(x) & x > 0]
[1] 0.25171708 0.18031701 0.61580651 0.15191893 0.03523937 1.77489019
正整数索引
在上面的例子中,我们已经用x[1:10]
来提取x
的前10个元素。在R
中第一个元素的索引是1
,但在许多其他编程语言中,第一个元素的索引是0
。
那如果想获取x
中第3
,第5
,第7
个元素应该是怎么做呢?这个时候,就可以用到c()
函数了。
> x[c(3, 5, 7)]
[1] NA NA -0.6588387
我们目前对子集的操作都是在x
的范围内的,如果我们要取x
的0
号元素会怎么样?
> x[0]
numeric(0)
返回的是numeric(0)
空值,注意空值不代表缺失值。虽然这个操作没有什么意义,但是R
并不会阻止它。下面再让我们看看超出x
长度的索引,比如x[3000]
> x[3000]
[1] NA
这次返回的是NA
,是一个缺失值。同样,没有什么用,但是R
不会阻止我们要求它。这应该是一个值得警惕的事情。我们应始终确保所要查找的内容在所使用向量的范围内。
负整数索引
现在考虑这样一个场景,我们想获取x
中除了第2
,第10
个元素之外的元素,应该怎么做?构建一个40
以内,除2、10
以外的数字索引是一个相当麻烦的事情。
这时候就可以用到负整数索引,要满足上诉场景的代码:
> x[c(-2, -10)]
[1] NA NA -0.05108979 NA -0.02086817 -0.65883869 NA -0.76755803 NA NA 0.25171708
[12] 0.18031701 -0.37318508 -0.98855340 -1.68402326 NA NA NA -0.99748631 NA NA NA
[23] NA -0.21191859 NA 0.61580651 0.15191893 -0.84210911 NA NA NA -0.02113655 NA
[34] NA 0.03523937 1.77489019 -0.16145833 -1.51209270
负整数索引还有另外一种写法,把-
号写在c()
函数前面:x[-c(2, 10)]
。大家可以试试是否等价。
字符串索引
到目前为止,我们已经介绍了三种索引向量:逻辑,正整数和负整数。剩下的唯一类型需要我们引入“命名”元素的概念。
首先,我们创建一个对元素命名的向量。
> vect <- c(foo = 11, bar = 2, norf = NA)
如果我们直接输出这个向量,其中的每个元素都会有自己的名字。
> vect
foo bar norf
11 2 NA
使用names()
函数可以获取向量中的元素名。
> names(vect)
[1] "foo" "bar" "norf"
还可以通过names()
函数来对向量的元素命名。
> vect2 <- c(11, 2, NA)
> names(vect2) <- c("foo", "bar", "norf")
现在我们可以使用identical()
函数来比较vect
和vect2
是否相同。
> identical(vect, vect2)
[1] TRUE
现在回到字符串索引的问题上来,如果我们要获取vect
的第2
个元素,可以怎么做?
> vect["bar"]
bar
2
同样,我们可以通过字符串获取多个元素,比如vect[c("foo", "bar")]
。
小结
从向量提取子集,有4
种索引。在不同的情况下,最好使用不同的方法。
•逻辑索引:通过逻辑表达式来获取;•正整数索引:希望获取向量范围内的元素;•负整数索引:可以排除向量范围内的某些元素;•字符串索引:对元素进行命名后,可以通过元素的命名获取元素
References
[1]
上一节: https://yantinger.com/6Da2A7Xqk/