vlambda博客
学习文章列表

R语言学习5-向量子集

在本课程中,我们将了解如何根据指定的条件从向量中提取元素。

例如,我们可能只对向量的前20个元素感兴趣,或者仅对非NA的元素感兴趣,或者对正数或与感兴趣的特定变量相对应的那些元素感兴趣。

现在有这么一个向量x,里面包含20个服从标准正态分布的数字和20NA

> 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的范围内的,如果我们要取x0号元素会怎么样?

> 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()函数来比较vectvect2是否相同。

> identical(vect, vect2)[1] TRUE

现在回到字符串索引的问题上来,如果我们要获取vect的第2个元素,可以怎么做?

> vect["bar"]bar  2

同样,我们可以通过字符串获取多个元素,比如vect[c("foo", "bar")]

小结

从向量提取子集,有4种索引。在不同的情况下,最好使用不同的方法。

逻辑索引:通过逻辑表达式来获取;正整数索引:希望获取向量范围内的元素;负整数索引:可以排除向量范围内的某些元素;字符串索引:对元素进行命名后,可以通过元素的命名获取元素

References

[1] 上一节: https://yantinger.com/6Da2A7Xqk/