Lesson 6: 子集向量

在这节课中,我们将看到如何根据我们指定的一些条件从向量中提取元素。

例如,我们也许只对一个向量的前 20 个元素感兴趣,活着仅对那些不是 NA 的元素感兴趣,或者只对那些是正的或者对应于一个特定的感兴趣的元素感兴趣。本课结束时,你将了解如何处理这些场景。

我们已经创建了一个向量 x,它包含了从标准正态分布中随机选取的 20 个数字,以及 20 个 NA。现在输入 x,看它是否是这样的:

> x
 [1]          NA          NA -0.01301518          NA          NA          NA
 [7] -0.47721718          NA  0.23556194          NA          NA          NA
[13] -0.56827616          NA -1.39451656  0.20122132  0.09755386  2.47619742
[19] -0.08464506  0.80707804 -0.28220555 -0.85445817  1.65740981          NA
[25]          NA  0.19560065          NA          NA -0.84176773  0.30555518
[31]          NA  0.27902072          NA          NA  0.91157021          NA
[37]          NA -0.70343162          NA -0.64953318

你告诉 R 你想从向量中选择一部分元素(比如:一个子集)的方法是在向量的名字后面的方括号中放置一个“索引向量”。

比如一个简单的例子,试一下 x[1:10] 来查看向量 x 的前 10 个元素。

> x [1:10]
 [1]          NA          NA -0.01301518          NA          NA          NA
 [7] -0.47721718          NA  0.23556194          NA

索引向量有四种不同的形式:逻辑向量,正整数的向量,负整数的向量,字符串的向量。每一个我们在这节课都会讲到。

让我们从逻辑向量建立索引开始。在处理真实数据时,一个常见的场景时我们想要提取一个向量中不是 NA 的所有元素。回想一下,is.na(x) 生成了一个长度于 x 相同的逻辑值向量,其 TRUE 对应于 x 中的 NA,FALSE 对应于 x 中的非 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 值。

回想一下,! 给我们一个逻辑表达式的否定式,所有 !is.na(x) 可以被解读为 is not NA。因此,我们想要创建一个包含所有来自 x 的非 NA 值的向量 y,我们可以使用 y <- x[!is.na(x)], 试试吧:

> y <- x[!is.na(x)]
> y
 [1]  1.58802569 -1.01293755  0.37155713  1.69750561 -1.60847397  0.60249903
 [7] -0.41862256 -0.48870077  1.18646771 -0.54252969 -0.97333657  1.13544799
[13]  0.06677423  0.56186192  0.16981586 -1.26339820 -0.78870739 -0.41639811
[19] -0.17735571 -2.33724788

现在我们已经隔离了 x 的非缺失值,并将它们放入 y 中,子集 y 就是我们想要的。

回想一下,表达式 y > 0 将给我们一个逻辑值向量,它的长度与 y 相同,TRUE 对应于大于 0 的 y 的值,FALSE 对应于小于等于 0 的 y 的值。你认为 y[y > 0] 会返回什么?试一下:

> y [y > 0]
[1] 1.58802569 0.37155713 1.69750561 0.60249903 1.18646771 1.13544799 0.06677423
[8] 0.56186192 0.16981586

你也许想知道为什么我们一开始不用 x[x > 0] 来提取 x 中的正值元素,试一下看下结果:

> x [x > 0]
 [1]         NA         NA         NA 1.58802569         NA         NA
 [7] 0.37155713         NA 1.69750561         NA 0.60249903         NA
[13]         NA         NA 1.18646771         NA         NA 1.13544799
[19]         NA 0.06677423         NA         NA 0.56186192 0.16981586
[25]         NA         NA         NA         NA         NA

因为 NA 不是一个值,而是一个未知数的占位符,所以表达式 NA > 0 的结果为 NA。因此,当我们这样做的时候,我们得到了一堆和我们的正数混合在一起的 NA。

结合逻辑运算和子集的知识,我可以这样做,x[!is.na(x) & x > 0],试一下:

> x [!is.na(x) & x > 0]
[1] 1.58802569 0.37155713 1.69750561 0.60249903 1.18646771 1.13544799 0.06677423
[8] 0.56186192 0.16981586

在本例中,我们只请求了非缺失值且大于零的 x 值。

我已经向您展示了如何使用 x[1:10] 来子集化 x 的前十个值。在本例中,我们在方括号内提供了一个正整数向量,它告诉 R 只返回编号为 1 到 10 的 x 的元素。

许多编程语言使用所谓的“从零开始的索引”,这意味着向量的第一个元素被认为是元素 0。R 使用“基于 1 的索引”,这意味着一个向量的第一个元素被认为是元素 1。

您能指出我们如何将 x 的第 3、5 和 7 个元素子集化吗? 提示:使用 c() 函数将元素编号指定为数字向量。

> x [c(3, 5, 7)]
[1] 1.969917       NA       NA

重要的是,当使用整数向量来子集化向量 x 时,我们坚持使用索引集 {1, 2, ..., 40}, 因为 x 只有 40 个元素。如果我们提取 x 的第 0 个元素(即 x [0] ),试一下会发生什么。

> x [0]
numeric(0)

正如你所料,我们没有得到任何有用的东西。不行的是,R 并灭有阻止我们这样做。如果我们提取 x 的第 3000 个元素呢,试一下。

> x [3000]
[1] NA

同样,没什么有用的,但 R 不阻止我们提出要求。这是个警示。你应该确保你所提取的是在你所处理向量的范围内。

如果我们对 x 除了第 2 个和第 10 个元素以外的所有元素感兴趣呢?如果列出所有的数字索引将是很乏味的。

幸运的是,R 接受负整数索引。x[c(2, 10)] 只给出了 x 的第 2 和第 10 个元素,而 x[c(-2, -10)] 给出了除第 2 和第 10 个以外的所有 x 的元素。输入 x[c(-2, -10)] 来看看。

> x [c(-2, -10)]
 [1]          NA  1.96991716 -0.00232278          NA          NA          NA
 [7]          NA          NA          NA -0.11091275  0.10989098          NA
[13]  0.27947713 -0.57222361          NA  0.65100583 0.41413828 -0.64963226
[19] -0.15977023          NA          NA          NA 1.53372448 -0.47685392
[25]          NA -0.25140323  1.40447082          NA 1.47180257          NA
[31]          NA  1.47247464          NA -0.08781325 0.78578649          NA
[37]          NA  1.90042642

指定多个负数的一种简便方法是将负数放在正数向量的前面。输入 x[-c(2, 10)] 来得到完全相同的结果。

> x [-c(2, 10)]
 [1]          NA  1.96991716 -0.00232278          NA          NA          NA
 [7]          NA          NA          NA -0.11091275  0.10989098          NA
[13]  0.27947713 -0.57222361          NA  0.65100583 0.41413828 -0.64963226
[19] -0.15977023          NA          NA          NA 1.53372448 -0.47685392
[25]          NA -0.25140323  1.40447082          NA 1.47180257          NA
[31]          NA  1.47247464          NA -0.08781325 0.78578649          NA
[37]          NA  1.90042642

到目前为止,我们已经介绍了三种类型的索引向量,逻辑型,正整数型和负整数型。剩下的唯一类型要求我们引入“命名”元素的概念。

创建一个包含三个命名元素的数字向量 vect <- c(foo = 11, bar = 2, norf = NA).

> vect <- c(foo = 11, bar = 2, norf = NA)

当我们将 vect 打印到控制台时,你将看到每个元素都有一个名称。试一下。

> vect
 foo  bar norf
  11    2   NA

我们还可以通过将 vect 作为参数传递给 names() 函数来获得 vect 的名称。试试吧。

> names(vect)
[1] "foo"  "bar"  "norf"

活着,我们可以用 c(11, 2, NA) 创建一个未命名的向量 vect2. 现在试一下。

> c(11, 2, NA)
[1] 11  2 NA

创建一个名为 vect2 的普通(未命名)向量,其中包含 c(11, 2, NA).

> vect2 <- c(11, 2, NA)

然后,我们可以使用 names(vect2) <- c("foo", "bar", "norf")names 属性添加到 vect2 中。去做吧。

> names(vect2) <- c("foo", "bar", "norf")

现在,让我们利用 identical() 函数来检查 vect 和 vect2 是否相同。

> identical(vect, vect2)
[1] TRUE

事实上,vect 和 vect2 是相同的命名向量。

现在,回到通过命名元素设置向量子集的问题上。你认为下面哪一个会提取出 vect 的第二个元素?

1: vect [bar]
2: vect ["2"]
3: vect ["bar"]

答案是第三个,试一下。

> vect ["bar"]
bar
  2

同样,我们可以用 vect[c("foo", "bar")] 来指定一个名称向量。试一下。

> vect [c("foo", "bar")]
foo bar
 11   2

现在你已经了解了从向量中设置数据子集的四种方法。不同的方法在不同的情况下是最好的,如有疑问,尝试一下!

Copyright © xresearcher.com 2020 all right reserved,powered by Gitbook该文件修订时间: 2020-03-18 22:32:57

results matching ""

    No results matching ""