4 数值型向量及其运算

4.1 数值型向量

向量是将若干个基础类型相同的值存储在一起, 各个元素可以按序号访问。 如果将若干个数值存储在一起可以用序号访问, 就叫做一个数值型向量。

c()函数把多个元素或向量组合成一个向量。如

## [1] 1 2 3 4

10:13这样的写法表示从10到13的整数组成的向量。

print()函数显示向量或在命令行中显示向量时, 每行显示的行首会有方括号和数字序号, 代表该行显示的第一个向量元素的下标。如

##  [1] 12345678901 12345678902 12345678903 12345678904 12345678905 12345678906
##  [7] 12345678907 12345678908 12345678909 12345678910 12345678911 12345678912
## [13] 12345678913 12345678914 12345678915 12345678916 12345678917 12345678918
## [19] 12345678919 12345678920

length(x)可以求x的长度。 长度为零的向量表示为numeric(0)numeric()函数可以用来初始化一个指定元素个数而元素都等于零的数值型向量, 如numeric(10)会生成元素为10个零的向量。

4.2 向量运算

4.2.1 标量和标量运算

单个数值称为标量, R没有单独的标量类型, 标量实际是长度为1的向量。

R中四则运算用+ - * / ^表示(加、减、乘、除、乘方),如

## [1] 10.72

R中四则运算仍遵从通常的优先级规则, 可以用圆括号()改变运算的先后次序。 如

## [1] 5.56

除了加、减、乘、除、乘方, R还支撑整除运算和求余运算。 用%/%表示整除,用%%表示求余。如

## [1] 1
## [1] 2
## [1] 2
## [1] 0.1

4.2.2 向量与标量运算

向量与标量的运算为每个元素与标量的运算, 如

## [1]  3 12
## [1] -1  8
## [1]  2 20
## [1] 0.5 5.0
## [1]   1 100
## [1] 2.0 0.2
## [1]    2 1024

一个向量乘以一个标量, 就是线性代数中的数乘运算。

四则运算时如果有缺失值,缺失元素参加的运算相应结果元素仍缺失。 如

## [1] 11 NA 13

4.2.3 等长向量运算

等长向量的运算为对应元素两两运算。 如

## [1]  5 12
## [1] -3  8
## [1]  4 20
## [1] 0.25 5.00

两个等长向量的加、减运算就是线性代数中两个向量的加、减运算。

4.2.4 不等长向量的运算

两个不等长向量的四则运算, 如果其长度为倍数关系,规则是每次从头重复利用短的一个。 如

## [1] 11 23 15 27
## [1]  10  60  50 140

不仅是四则运算,R中有两个或多个向量按照元素一一对应参与某种运算或函数调用时, 如果向量长度不同,一般都采用这样的规则。

如果两个向量的长度不是倍数关系,会给出警告信息。如

## Warning in c(1, 2) + c(1, 2, 3): 长的对象长度不是短的对象长度的整倍数
## [1] 2 4 4

4.3 向量函数

4.3.1 向量化的函数

R中的函数一般都是向量化的: 在R中, 如果普通的一元函数以向量为自变量,一般会对每个元素计算。 这样的函数包括sqrt, log10, log, exp, sin, cos, tan等许多。 如

## [1] 1.0 2.0 2.5

为了查看这些基础的数学函数的列表,运行命令help.start(), 点击链接“Search Engine and Keywords”, 找到“Mathematics”栏目, 浏览其中的“arith”和“math”链接中的说明。 常用的数学函数有:

  • 舍入:ceiling, floor, round, signif, trunc, zapsmall
  • 符号函数 sign
  • 绝对值 abs
  • 平方根 sqrt
  • 对数与指数函数 log, exp, log10, log2
  • 三角函数 sin, cos, tan
  • 反三角函数 asin, acos, atan, atan2
  • 双曲函数 sinh, cosh, tanh
  • 反双曲函数 asinh, acosh, atanh

有一些不太常用的数学函数:

  • 贝塔函数 beta, lbeta
  • 伽玛函数 gamma, lgamma, digamma, trigamma, tetragamma, pentagamma
  • 组合数 choose, lchoose
  • 富利叶变换和卷积 fft, mvfft, convolve
  • 正交多项式 poly
  • 求根 polyroot, uniroot
  • 最优化 optimize, optim
  • Bessel函数 besselI, besselK, besselJ, besselY
  • 样条插值 spline, splinefun
  • 简单的微分 deriv

如果自己编写的函数没有考虑向量化问题, 可以用Vectorize()函数将其转换成向量化版本。

4.3.2 排序函数

sort(x)返回排序结果。 rev(x)返回把各元素排列次序反转后的结果。 order(x)返回排序用的下标。如

## [1] 11 33 55
## [1] 55 33 11
## [1] 3 1 2
## [1] 11 33 55

例子中, order(x)结果中3是x的最小元素11所在的位置下标, 1是x的第二小元素33所在的位置下标, 2是x的最大元素55所在的位置下标。

4.3.3 统计函数

sum(求和), mean(求平均值), var(求样本方差), sd(求样本标准差), min(求最小值), max(求最大值), range(求最小值和最大值)等函数称为统计函数, 把输入向量看作样本,计算样本统计量。 prod求所有元素的乘积。

cumsum和cumprod计算累加和累乘积。如

## [1]  1  3  6 10 15
## [1]   1   2   6  24 120

其它一些类似函数有pmax, pmin, cummax, cummin等。

4.3.4 生成规则序列的函数

seq函数是冒号运算符的推广。 比如,seq(5)等同于1:5seq(2,5)等同于2:5seq(11, 15, by=2)产生11,13,15。 seq(0, 2*pi, length.out=100)产生从0到\(2\pi\)的等间隔序列, 序列长度指定为100。

从这些例子可以看出,S函数可以带自变量名调用。 每个函数的变量名和用法可以查询其帮助信息, 在命令行界面用“?函数名”的方法查询。 在使用变量名时次序可以颠倒, 比如seq(to=5, from=2)}仍等同于2:5

rep()函数用来产生重复数值。 为了产生一个初值为零的长度为n的向量, 用x <- rep(0, n)rep(c(1,3), 2)把第一个自变量重复两次, 结果相当于c(1,3,1,3)

rep(c(1,3), c(2,4))则需要利用R的一般向量化规则, 把第一自变量的第一个元素1按照第二自变量中第一个元素2的次数重复, 把第一自变量中第二个元素3按照第二自变量中第二个元素4的次数重复, 结果相当于c(1,1,3,3,3,3)

如果希翼重复完一个元素后再重复另一元素,用each=选项, 比如rep(c(1,3), each=2)结果相当于c(1,1,3,3)

有一点技术性的小问题: 1:5seq(5)的结果是整型(integer)的, c(1,3,5)seq(1, 5, by=2)的结果是浮点型(double)的。

4.4 复数向量

复数常数表示如3.5+2.4i, 1i。 用函数complex()生成复数向量, 指定实部和虚部。 如complex(real = c(1,0,-1,0), imaginary = c(0,1,0,-1))相当于c(1+0i, 1i, -1+0i, -1i)

complex()中可以用modarg指定模和辐角,如 complex(mod=1, arg=(0:3)/2*pi)结果同上。

Re(z)z的实部, 用Im(z)求z的虚部, 用Mod(z)abs(z)求z的模, 用Arg(z)求z的辐角, 用Conj(z)求z的共轭。

sqrt, log, exp, sin等函数对复数也有定义, 但是函数定义域在自变量为实数时可能有限制而复数无限制, 这时需要区分自变量类型。如

4.5 练习

  1. 显示1到100的整数的平方根和立方根(提示:立方根就是三分之一次方)。

  2. 设有10个人的小测验成绩为: \[ 77\ 60\ 91\ 73\ 85\ 82\ 35\ 100\ 66\ 75 \]

    1. 把这10个成绩存入变量x;

    2. 从小到大排序;

    3. 计算order(x),说明order(x)结果中第3项代表的意义。

    4. 计算这些成绩的平均值、标准差、最小值、最大值、中位数。

  3. 生成\([0,1]\)区间上等间隔的100个格子点存入变量x中。