第 6 章 运算符及向量运算

向量是R语言中最基础的数据结构,自然地我们会很关注向量的运算,事实上,R语言的强大优势就体现在向量运算上。当然,这都归功于R语言强大的向量化操作。 在此之前,先介绍常用的有以下几种运算符类型:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 其他运算符

6.1 算术运算符

  • + 两个向量相加
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a + b
## [1] 5 7 9
  • - 两个向量相减
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a - b
## [1] -3 -3 -3
  • * 两个向量相乘
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a * b
## [1]  4 10 18
  • / 将第一个向量与第二个向量相除
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a / b
## [1] 0.25 0.40 0.50
  • %% 两个向量求余
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a %% b
## [1] 1 2 3
  • %/% 两个向量相除求商
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a %/% b
## [1] 0 0 0
  • %*% 两个向量的内积,也称为点乘

对于向量

a <- c(1, 2, 3)
b <- c(4, 5, 6)
a %*% b
##      [,1]
## [1,]   32

此运算符也用于将矩阵相乘

m <- matrix(c(1:4), ncol = 2)
m %*% m
##      [,1] [,2]
## [1,]    7   15
## [2,]   10   22
  • ^ 将第二向量作为第一向量的指数
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a ^ b
## [1]   1  32 729

6.2 循环补齐(recycling)

做算术运算时,当两个向量长度相等的时候,就一一对应的完成计算;当两个向量长度不相等的时候,短的向量会循环补齐,保持与长向量的长度一致后,再做运算。

  • 长向量的长度正好是短向量的整数倍
x <- 1
y <- c(10, 20, 30, 40)
x + y
## [1] 11 21 31 41
x <- c(1, 2)
y <- c(10, 20, 30, 40)
x * y
## [1] 10 40 30 80
  • 长向量的长度不是短向量的整数倍
x <- c(1, 2, 3)
y <- c(10, 20, 30, 40, 50, 60, 70)
x + y
## [1] 11 22 33 41 52 63 71
x <- c(1, 2, 3)
y <- c(10, 20, 30, 40, 50, 60, 70)
x * y
## [1]  10  40  90  40 100 180  70

长度不是整数倍关系的时候,R语言会提出友好的警告,这个警告是非常有必要的,一方面提醒写代码的人是不是写漏了一些数据,另一方面提醒会给看代码的人产生迷惑。因此,为了代码的可读性,除非某一个向量长度为1,我们尽可能避免长度不一致的向量之间的运算。

6.3 关系运算符

将第一向量的每个元素与第二向量的相应元素进行比较,比较的结果是布尔值,布尔值是“真” TRUE 或“假” FALSE 中的一个。

  • > 检查第一向量的每个元素是否大于第二向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a > b
## [1] FALSE FALSE FALSE
  • < 检查第一个向量的每个元素是否小于第二个向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a < b
## [1] TRUE TRUE TRUE
  • == 检查第一个向量的每个元素是否等于第二个向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a == b
## [1] FALSE FALSE FALSE
  • <= 检查第一向量的每个元素是否小于或等于第二向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a <= b
## [1] TRUE TRUE TRUE
  • >= 检查第一向量的每个元素是否大于或等于第二向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a >= b
## [1] FALSE FALSE FALSE
  • != 检查第一个向量的每个元素是否不等于第二个向量的相应元素。
a <- c(1, 2, 3)
b <- c(4, 5, 6)
a != b
## [1] TRUE TRUE TRUE

6.4 逻辑运算符

逻辑运算符,一般适用于逻辑类型的向量。

  • & 元素逻辑AND运算符。 它将第一向量的每个元素与第二向量的相应元素组合,并且如果两个元素都为TRUE,则给出输出TRUE。
a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
a & b
## [1] FALSE FALSE FALSE
  • | 元素逻辑或运算符。 它将第一向量的每个元素与第二向量的相应元素组合,并且如果元素有一个为真,则给出输出TRUE。
a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
a | b
## [1]  TRUE  TRUE FALSE
  • ! 它被称为逻辑非运算符。 对于向量的每个元素,给出相反的逻辑值。
a <- c(TRUE, FALSE, FALSE)
!a
## [1] FALSE  TRUE  TRUE

逻辑运算符 &&|| 只考虑向量的第一个元素,给出单个元素的向量作为输出。

&& 称为逻辑AND运算符。 取两个向量的第一个元素,并且只有两个都为TRUE时才给出TRUE。

a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
a && b
## [1] FALSE

|| 称为逻辑OR运算符。 取两个向量的第一个元素,如果其中一个为TRUE,则给出TRUE。

a <- c(TRUE, FALSE, FALSE)
b <- c(FALSE, TRUE, FALSE)
a || b
## [1] TRUE

6.5 其他运算符

  • : 冒号运算符。它按顺序创建一个整数序列。
a <- 1:10
a
##  [1]  1  2  3  4  5  6  7  8  9 10
## [1] "integer"

我们在第 4 章向量部分,提到seq()函数,也能产生序列

b <- seq(from = 1, to = 10, by = 1)
b
##  [1]  1  2  3  4  5  6  7  8  9 10
## [1] "double"

注意到a是整数类型,而b是双精度的数值型。

  • %in% 此运算符用于判断元素是否属于向量。
c(2, 3, 7) %in% c(1, 2, 3, 4, 5)
## [1]  TRUE  TRUE FALSE
  • is.na() 判断是否为缺失值,R 里缺失值NA表示,NA的意思就是 not available 或者 not applicable.
is.na(c(1, 2, NA, 4, NA, 6))
## [1] FALSE FALSE  TRUE FALSE  TRUE FALSE
x <- c(1, 2, NA, 4, NA, 6)
!is.na(x)
## [1]  TRUE  TRUE FALSE  TRUE FALSE  TRUE

6.6 特殊值

R 语言里还有一些特殊的值: Inf, NaN, NANULL.

  • Inf,是Infinity的简写,表示无限大;-Inf表示无限小,比如我们用1除以0:
1/0
## [1] Inf
  • NaN,是Not a Number的简写,表示这个数字没有数学定义,比如
0/0
## [1] NaN
  • NA,是Not available的简写,表示缺失状态。在后面章节中,当我们处理数据框或者向量的时候回经常遇到它。

  • NULL,是No value的意思,表示没有值,或者空值的意思,表示变量实际上没有任何值,或者甚至不存在。

# NULL: an *entire* vector is absent
c(    )
## NULL
# NA: an *element* in a vector is absent
c(1, NA, 3)
## [1]  1 NA  3

6.7 习题

  • 自己填入向量,并运算
___ + ___
___ - ___
___ / ___
___ * ___
___ ^ ___

___ == ___
___ != ___
___ < ___
___ > ___
___ <= ___
___ >= ___

___ & ___
___ | ___

___ %in% ___
is.na(___ )
  • 说出向量 a 和 b 的差异在什么地方?
a <- 1:10
b <- seq(from = 1, to = 10, by = 1)
identical(a, b)