10 Basic: regular operations
R 中可以执行各式各样的操作,这些操作都是通过使用 operator 或 function 实现。常见的操作有:
- 基本数学运算
- 关系和逻辑
- 筛选和排序
- 其他
注意:绝大多数 operators 和 functions 都支持 recycling rule(详见7.2.2)。
由于 subsetting operator 进阶用法的第二步是将拆解的步骤(操作)转换成相应的代码,所以本节中将重点演示如何将部分 operator 和 function 运用在 subsetting 中。
10.1 Basic mathematical operations
10.1.1 Arithmetic operators
+
-
*
/
^
%%
%/%
%*%
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) %% 5 # 求余数
#> [1] 1 2 3 4 0 1 2 3 4 0
c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) %/% 5 # 整除
#> [1] 0 0 0 0 1 1 1 1 1 2
m1 <- matrix(c(1, 2, 3, 4, 5, 6), 3, 2)
m1
#> [,1] [,2]
#> [1,] 1 4
#> [2,] 2 5
#> [3,] 3 6
m2 <- matrix(c(1, 2, 3, 4, 5, 6), 2, 3)
m2
#> [,1] [,2] [,3]
#> [1,] 1 3 5
#> [2,] 2 4 6
m1 %*% m2 # 矩阵乘法
#> [,1] [,2] [,3]
#> [1,] 9 19 29
#> [2,] 12 26 40
#> [3,] 15 33 51
10.1.2 Functions
10.1.2.5 Round
-
round(x, digits = 0)
,取整,规则是 4 舍 6 入,逢 5 成双,即逢 5 时向最近的偶数取整,保留digits
位小数,默认为 0; -
floor(x)
,向下取整; -
ceiling(x)
,向上取整; -
trunc(x)
,保留整数部分,舍弃小数部分。
![](images/operation%20round.png)
10.1.2.6 Natrual exponential and logorithm
exp(x)
,自然指数 \(e^{x}\)
log(x, base = exp(1))
,对数 \(\log_{base}x\),base
的默认值是exp(1)
:
10.1.2.7 Others
- Square root:
sqrt(x)
,即\(\sqrt{x}\)。 - Trigonometric Functions:
sin(x)
,cos(x)
,tan(x)
- Absolute value:
abs(x)
,即\(|x|\)。 - Sign:(正数输出 1,负数输出 -1)
sign(x)
- Transpose
t(x)
,即\(x'\)或\(x^T\),将x
转置(沿主对角线反转,行列互换),x
可以是 matrix 或 data.frame。
a <- matrix(c(1, 2, 3, 4, 5, 6), 3, 2)
a
#> [,1] [,2]
#> [1,] 1 4
#> [2,] 2 5
#> [3,] 3 6
t(a)
#> [,1] [,2] [,3]
#> [1,] 1 2 3
#> [2,] 4 5 6
例子:数据转换(Skewed Distribution: Definition, Examples)
![](images/operation%20arithmetic%20example%20data%20transformation.png)
10.2 Relational and Logical operators
10.2.1 Relational operators
>
,<
,>=
,<=
,==
,!=
。这些 operators 返回的结果都是 logical:
m1 <- matrix(c(-1, -2, 0, 4), 2, 2)
# 以下代码全部都受到 recycling rule 的作用
m1 > 0
#> [,1] [,2]
#> [1,] FALSE FALSE
#> [2,] FALSE TRUE
m1 < 0
#> [,1] [,2]
#> [1,] TRUE FALSE
#> [2,] TRUE FALSE
m1 >= 0
#> [,1] [,2]
#> [1,] FALSE TRUE
#> [2,] FALSE TRUE
m1 <= 0
#> [,1] [,2]
#> [1,] TRUE TRUE
#> [2,] TRUE FALSE
m1 == 0
#> [,1] [,2]
#> [1,] FALSE TRUE
#> [2,] FALSE FALSE
m1 != 0
#> [,1] [,2]
#> [1,] TRUE FALSE
#> [2,] TRUE TRUE
其中,在使用==
时需要注意,object == NA
、object == NaN
,object == NULL
都是错误写法:
1 == NA
#> [1] NA
1 == NaN
#> [1] NA
1 == NULL
#> logical(0)
若想要检测某个 object 究竟是不是NA
、NaN
或NULL
,正确的写法应该是:
is.na(c(1, 2, NA))
#> [1] FALSE FALSE TRUE
is.nan(c(1, 2, NaN))
#> [1] FALSE FALSE TRUE
is.null(c(1, 2, NULL))
#> [1] FALSE
Relational operators 在 subsetting 的进阶写法中十分常用。例如,实训 3-2 第 1 题第 4 小问,剔除“Pick场数”低于 200 的英雄的所有数据:
library(openxlsx)
data_ori <- read.xlsx("F:/Nutstore backup/R/codes/RBA/data/Arena of Valor_midterm dataset.xlsx")
head(data_ori)
#> 角色名 职业 移速 攻击范围 生存能力 攻击伤害 上手难度
#> 1 曜 战士 370 近程 5 7 6
#> 2 西施 法师 360 远程 6 8 6
#> 3 嫦娥 法师 395 远程 10 10 5
#> 4 盘古 战士 380 近程 10 8 6
#> 5 瑶 辅助 360 远程 10 7 5
#> 6 上官婉儿 法师 396 远程 5 7 6
#> Pick场数 总击杀 场均击杀 场均死亡 场均助攻 Ban场数 胜率
#> 1 11 16 1.45 2.00 3.45 1 0.45
#> 2 175 222 1.27 1.62 6.90 161 0.54
#> 3 64 168 2.58 1.86 5.11 80 0.46
#> 4 95 248 2.61 2.61 5.41 50 0.49
#> 5 53 24 0.45 2.49 7.19 66 0.40
#> 6 55 163 2.96 3.24 3.78 74 0.45
#> Ban率 热度
#> 1 0.00 0.01
#> 2 0.20 0.42
#> 3 0.10 0.18
#> 4 0.06 0.18
#> 5 0.08 0.15
#> 6 0.09 0.16
data_200 <- data_ori[c(-7, -13, -15, -16)]
data_200 <- data_200[data_200[, 7] >= 200, ]
![](images/operation%20relation%20example%20subsetting.png)
Basic mathematical operations 和 relational operators 的组合也是 subsetting 进阶写法中常用手段。例如,取绝对值最大的数:
10.2.2 Logical operator
10.2.2.1 &
and &&
基本结构:LHS & RHS
,LHS && RHS
。
LHS
(left hand side)和RHS
(right hand side)的结果是长度为 1 的 logical vector 时,&
和&&
等价。
LHS |
RHS |
结果 |
---|---|---|
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
FALSE |
FALSE |
TRUE |
FALSE |
FALSE |
FALSE |
FALSE |
a <- 3
a > 2 & a < 4
#> [1] TRUE
a > 2 && a < 4
#> [1] TRUE
LHS
和RHS
的结果是长度大于 1 的 logical vector 时,&
和&&
的结果不同。&
会比较左右两侧的 logical vector 中每一对 element,&&
会从左往右比,直到有结果为止,本质上相当于只会比较第一个位置上的那对 elements,也正是因为如此,从 4.3.0 开始,R 强制要求&&
的LHS
和RHS
的长度只能为1(因为只比第一个位置),否则就报错,这点在&&
的帮助页面也有明确说明(详见?`&&`
):
a <- c(1, 2, 3, 4, 5)
a >= 1
#> [1] TRUE TRUE TRUE TRUE TRUE
a <= 3
#> [1] TRUE TRUE TRUE FALSE FALSE
a >= 1 & a <= 3
#> [1] TRUE TRUE TRUE FALSE FALSE
a >= 1 && a <= 3
#> Error in a >= 1 && a <= 3: 'length = 5' in coercion to 'logical(1)'
10.2.2.2 |
and ||
基本结构:LHS | RHS
,LHS || RHS
。
当LHS
(left hand side)和RHS
(right hand side)的结果是长度为 1 的 logical vector 时,|
和||
等价。
LHS |
RHS |
结果 |
---|---|---|
TRUE |
TRUE |
TRUE |
TRUE |
FALSE |
TRUE |
FALSE |
TRUE |
TRUE |
FALSE |
FALSE |
FALSE |
a <- 6
a < 2 | a > 4
#> [1] TRUE
a < 2 || a > 4
#> [1] TRUE
当LHS
和RHS
(的结果是长度大于 1 的 logical vector 时,|
会比较左右两侧的 logical vector 中每一对 element,||
则会报错:
a <- c(1, 2, 3, 4, 5)
a <= 2
#> [1] TRUE TRUE FALSE FALSE FALSE
a >= 4
#> [1] FALSE FALSE FALSE TRUE TRUE
a <= 2 | a >= 4
#> [1] TRUE TRUE FALSE TRUE TRUE
a >= 1 || a <= 3
#> Error in a >= 1 || a <= 3: 'length = 5' in coercion to 'logical(1)'
注意,如果&
和|
左右两边的expr
长度不一,会触发 recycling rule (详见7.2.2)。
10.2.2.3 !
基本结构:!expr
。若expr
的结果是TRUE
,则改为FALSE
;若FALSE
则改为TRUE
:
a <- c(1, 2, 3, 4, 5)
a <= 2
#> [1] TRUE TRUE FALSE FALSE FALSE
!(a <= 2)
#> [1] FALSE FALSE TRUE TRUE TRUE
!is.na(a)
#> [1] TRUE TRUE TRUE TRUE TRUE
Relational operator 和 logical operator 组合使用,可以非常便捷完成按照指定条件 subsetting 的任务,尤其是当需要满足的条件较多时:
m1 <- matrix(runif(25), 5, 5)
m1
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.7478078 0.91596854 0.5769906 0.7134575 0.6338611
#> [2,] 0.6635342 0.20744560 0.8836200 0.0595439 0.7726311
#> [3,] 0.9190690 0.82164510 0.6132203 0.6552251 0.5922140
#> [4,] 0.8283002 0.09616326 0.7919639 0.6813751 0.2300083
#> [5,] 0.1193508 0.36839487 0.5131677 0.1567600 0.4214387
m1[m1 > 0.2 & m1 < 0.8]
#> [1] 0.7478078 0.6635342 0.2074456 0.3683949 0.5769906
#> [6] 0.6132203 0.7919639 0.5131677 0.7134575 0.6552251
#> [11] 0.6813751 0.6338611 0.7726311 0.5922140 0.2300083
#> [16] 0.4214387
m1[m1 < 0.3 | m1 > 0.7]
#> [1] 0.74780778 0.91906898 0.82830022 0.11935081 0.91596854
#> [6] 0.20744560 0.82164510 0.09616326 0.88361995 0.79196388
#> [11] 0.71345748 0.05954390 0.15675999 0.77263111 0.23000825
m1[!(m1 < 0.3 | m1 > 0.7)]
#> [1] 0.6635342 0.3683949 0.5769906 0.6132203 0.5131677
#> [6] 0.6552251 0.6813751 0.6338611 0.5922140 0.4214387
10.3 Locate, match and sort
10.3.1 Locate
which(x)
,输出x
中所有TRUE
的位置信息,x
必须是一个 logical object。
a <- runif(5)
a
#> [1] 0.75043587 0.13423118 0.87632186 0.08106923 0.21430288
which(a == max(a))
#> [1] 3
which(a > 0.5)
#> [1] 1 3
which(a > 0.1 & a < 0.9)
#> [1] 1 2 3 5
使用which()
通常不是为了将符合条件的元素取出,而是为了将这些元素的位置找出来,起个名字并保存在 Environment 里,方便后续单独处理这些元素的时候可以直接使用位置索引信息来定位。如果只是需要将符合条件的所有元素取出来,只用 relational operator 就足够了。
a <- runif(5)
a
#> [1] 0.10977542 0.75191291 0.85675420 0.04648571 0.13118339
a[which(a > 0.5)]
#> [1] 0.7519129 0.8567542
a[a > 0.5]
#> [1] 0.7519129 0.8567542
如果x
是一个有dim
的array
或matrix
,which(x)
可以通过设定arr.ind = TRUE
来输出按dim
标识的 index:
10.3.2 Match
%in%
: 返回一个和逻辑向量,表示左边的值在右边的依据值中是否有匹配。
x %in% table
-
x
: 被匹配的值。 -
table
: 匹配时依据的值。
vec <- c(1, 2, 3)
vec_all <- c(6, 1, 5, 6, 1, 4, 4, 2, 10, 5)
vec %in% vec_all
#> [1] TRUE TRUE FALSE
vec_all %in% vec
#> [1] FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
#> [10] FALSE
%in%
可以用于挑选数据的指定列,例如:
vars <- c("x", "y", "z")
df <-
data.frame(
x = sample(5, 10, replace = TRUE),
n = sample(5, 10, replace = TRUE),
z = sample(5, 10, replace = TRUE),
m = sample(5, 10, replace = TRUE),
n = sample(5, 10, replace = TRUE),
y = sample(5, 10, replace = TRUE)
)
df_select <- df[names(df) %in% vars]
df_select
#> x z y
#> 1 2 3 3
#> 2 4 4 4
#> 3 2 1 5
#> 4 3 1 2
#> 5 2 2 2
#> 6 4 2 3
#> 7 4 3 1
#> 8 3 1 3
#> 9 4 5 2
#> 10 1 3 3
%in%
对于匹配的定义比==
考虑的更完备,对一些特殊的匹配情况做了处理,如NA
,只有匹配NA
时才会返回TRUE
的结果,否则返回FALSE
,
c(1, NA, 3) %in% c(1:10)
#> [1] TRUE FALSE TRUE
c(1, NA, 3) %in% NA # equivalent to is.na(c(1, NA, 3))
#> [1] FALSE TRUE FALSE
正是因为%in%
考虑更加完备,故%in%
可以替代==
,用在 subsetting 上,
df <- data.frame(x = c(1, NA, 1, 2, 4), y = c(2, 1, 1, 3, 5))
df$x == 1
#> [1] TRUE NA TRUE FALSE FALSE
df[df$x == 1 & df$y == 1, ]
#> x y
#> NA NA NA
#> 3 1 1
df[df$x %in% 1 & df$y %in% 1, ]
#> x y
#> 3 1 1
10.3.3 Sort
-
sort(x, decreasing = FALSE)
,将x
升序排列(默认),输出排列后的x
。decreasing
是可选 argument。decreasing = TRUE
则是按照降序排序列。
a <- runif(5)
a
#> [1] 0.9859356 0.9579676 0.8860316 0.3518951 0.8605600
sort(a)
#> [1] 0.3518951 0.8605600 0.8860316 0.9579676 0.9859356
sort(a, decreasing = TRUE)
#> [1] 0.9859356 0.9579676 0.8860316 0.8605600 0.3518951
-
order(..., decreasing = FALSE)
,...
是需一个或多个object
。decreasing
是可选argument
,decreasing = TRUE
表示按照降序排序列。
order()
输出的其实是 object 中的元素应该各自调整到哪个位置才能实现排序(升序或降序)。所以,order()
实际上给出的是位置信息。
- 无重复元素
![](images/operation%20order.png)
- 有重复元素
当输入的单个object
有重复元素(即ties
,表示一个独特的值同时有多个位置索引)时,默认是按照元素出现的先后顺序来排序,
如果有额外的线索可以区分重复元素时,order()
可以将这些重复元素按照额外线索排序,
score <- c(90, 95, 99, 95)
id <- c(4, 3, 2, 1)
order(score, id)
#> [1] 1 4 2 3
order(score, id, decreasing = TRUE)
#> [1] 3 2 4 1
总结一下,当输入 1 个 object 时,order()
排序的是这个object
;当输入多个object
时(这些object
都必须是同样长度),order()
排序的依旧是第一个object
,只不过该 object 中的重复元素是以第 2 个 object 中对应位置上的元素大小为依据,若这些元素依旧是重复的,则按照第 3 个 object 中对应位置上的元素大小为依据,依此类推。
order()
常用于根据某一列重新排列整个数据。例如根据score_math
降序排列:
data_set1 <- data.frame(name = c("小红", "小明", "小白", "小黑"),
id = c(1, 4, 2, 3),
score_math = c(90, 95, 98, 95))
data_set1[order(data_set1$score_math, id, decreasing = TRUE), ]
#> name id score_math
#> 3 小白 2 98
#> 2 小明 4 95
#> 4 小黑 3 95
#> 1 小红 1 90
order()
对字符也有效,默认升序,数字按从小到大,英文按字母,中文按拼音顺序,三者的优先级是数字 > 英文字母 > 中文拼音:
10.4 Others
10.4.1 Combine
-
c(...)
,将多个 object 合并成一个 vector,...
为要合并的 object。 -
cbind(...)
,将多个 objects,视作是 columns,将多个 object 横向合并成一个 object,...
为要合并的 object。 -
rbind(...)
,将多个 objects 视作是 rows,纵向合并成一个 object,...
为要合并的 object。
10.4.2 Get the number of
-
length(x)
,返回x
中 element 的个数; -
nrow(x)
或NROW(x)
,返回x
的行数,如果x
没有行数的信息,返回NULL
; -
ncol(x)
或NCOL(x)
,返回x
的列数,如果x
没有列数的信息,返回NULL
; -
nchar(x)
,返回x
各 element 的字符个数。
10.4.3 Generate sequence
10.4.3.1 Operator
from:to
,生成有序整数数列。from
为数列的起点;to
为数列的终点。
1:100
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13
#> [14] 14 15 16 17 18 19 20 21 22 23 24 25 26
#> [27] 27 28 29 30 31 32 33 34 35 36 37 38 39
#> [40] 40 41 42 43 44 45 46 47 48 49 50 51 52
#> [53] 53 54 55 56 57 58 59 60 61 62 63 64 65
#> [66] 66 67 68 69 70 71 72 73 74 75 76 77 78
#> [79] 79 80 81 82 83 84 85 86 87 88 89 90 91
#> [92] 92 93 94 95 96 97 98 99 100
:
可以用来生成行索引,在需要分半数据进行统计分析(交叉验证,复本信度等)时快速取出数据子集。以英雄联盟数据集为例:
10.4.3.2 Functions:
seq(from = 1, to = 1, by = ((to - from)/(length.out - 1)), length.out = NULL)
,生成有序数列。from
为数列的起点,to
为数列的终点。可选 argument:
-
by
为步长,即后一个数和前一个数之差; -
length.out
为生成数列的长度。
seq()
#> [1] 1
seq(from = 1, to = 100) # 等价于 1:100
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13
#> [14] 14 15 16 17 18 19 20 21 22 23 24 25 26
#> [27] 27 28 29 30 31 32 33 34 35 36 37 38 39
#> [40] 40 41 42 43 44 45 46 47 48 49 50 51 52
#> [53] 53 54 55 56 57 58 59 60 61 62 63 64 65
#> [66] 66 67 68 69 70 71 72 73 74 75 76 77 78
#> [79] 79 80 81 82 83 84 85 86 87 88 89 90 91
#> [92] 92 93 94 95 96 97 98 99 100
seq(1, 100, by = 3)
#> [1] 1 4 7 10 13 16 19 22 25 28 31 34 37 40
#> [15] 43 46 49 52 55 58 61 64 67 70 73 76 79 82
#> [29] 85 88 91 94 97 100
seq(1, 100, length.out = 34)
#> [1] 1 4 7 10 13 16 19 22 25 28 31 34 37 40
#> [15] 43 46 49 52 55 58 61 64 67 70 73 76 79 82
#> [29] 85 88 91 94 97 100
seq()
可以用于快速奇偶分半数据。以英雄联盟数据集为例:
library(openxlsx)
data_ori <- read.xlsx("F:/Nutstore backup/R/codes/RBA/data/Arena of Valor_midterm dataset.xlsx")
data_ori <- cbind(ID = 1:nrow(data_ori), data_ori)
data_subset1 <- data_ori[seq(1, nrow(data_ori), 2), ]
data_subset2 <- data_ori[seq(2, nrow(data_ori), 2), ]
rep(x, times = 1, length.out = NA, each = 1)
,生成重复序列。
rep(0, 3)
#> [1] 0 0 0
rep(c(1, 2, 3), 3)
#> [1] 1 2 3 1 2 3 1 2 3
rep(c(1, 2, 3), 3, length.out = 10)
#> [1] 1 2 3 1 2 3 1 2 3 1
rep(c(1, 2, 3), 3, length.out = 30, each = 3)
#> [1] 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1 1 1 2 2 2 3 3 3 1
#> [29] 1 1
rep()
可以巧妙地和subsetting
的操作相结合,来实现快速复制矩阵。例如以一个 \(2\times2\) 的矩阵为最小 element,复制出一个 \(2 \times 2\) 的大矩阵:
10.4.4 Random sampling
sample(x, size, replace = FALSE, prob = NULL)
,从x
中随机取出size
个元素。x
可以是一个 vector 或 integer scalar,当x
是 integer scalar 时,等价于1:x
;size
是 integer。可选 argument:
-
replace = TRUE
表示有放回抽样; -
prob
是一个向量,每一个元素是x
中对应元素被抽中的概率。
sample(5, 1) # 等价于 sample(5, 1, prob = rep(1/5, 5))
#> [1] 1
sample(5, 5)
#> [1] 4 3 2 5 1
sample(5, 5, replace = TRUE)
#> [1] 5 2 3 2 5
随机抽样的一个典型的应用场景是自助法(Bootstrap),从样本中随机取出多批指定大小的数据,当作是平行样本。以英雄联盟数据集为例:
10.4.5 Concatenate strings
paste(..., sep = " ", collapse = NULL)
,将object
按照指定方式拼接成字符串。...
是一个或多个待拼接的object
。可选argument
如下:
-
sep = " "
是拼接时用来分隔各项的字符串,默认值是一个英文空格; -
collapse = NULL
表示拼接好的各项最后合并成一个字符串,各项间用collapse
的值来分隔,默认值是NULL
,即不合并成一个字符串。
paste(1:12) # 等价于 as.character(1:12)
#> [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11"
#> [12] "12"
paste(1:12, "month")
#> [1] "1 month" "2 month" "3 month" "4 month" "5 month"
#> [6] "6 month" "7 month" "8 month" "9 month" "10 month"
#> [11] "11 month" "12 month"
paste(1:12, c("st", "nd", "rd", rep("th", 9)), "month")
#> [1] "1 st month" "2 nd month" "3 rd month" "4 th month"
#> [5] "5 th month" "6 th month" "7 th month" "8 th month"
#> [9] "9 th month" "10 th month" "11 th month" "12 th month"
paste(1:12, c("st", "nd", "rd", rep("th", 9)), "month", sep = "")
#> [1] "1stmonth" "2ndmonth" "3rdmonth" "4thmonth"
#> [5] "5thmonth" "6thmonth" "7thmonth" "8thmonth"
#> [9] "9thmonth" "10thmonth" "11thmonth" "12thmonth"
paste(1:12, c("st", "nd", "rd", rep("th", 9)), "month", sep = "", collapse = ",")
#> [1] "1stmonth,2ndmonth,3rdmonth,4thmonth,5thmonth,6thmonth,7thmonth,8thmonth,9thmonth,10thmonth,11thmonth,12thmonth"
paste()
可用于自动生成符合要求的文件名:
num_subsets <- 10
filenames <- paste(1:num_subsets,
".txt",
sep = "")
filenames
#> [1] "1.txt" "2.txt" "3.txt" "4.txt" "5.txt" "6.txt"
#> [7] "7.txt" "8.txt" "9.txt" "10.txt"
write.table(data_subset1, filenames[1])
write.table(data_subset2, filenames[2])
只要是需要按照一定的规律生成字符串,就要想到paste()
。
10.4.6 Print to console
有 2 个十分常用的 functions:print()
和cat()
。
-
print(x)
,将x
的 value 输出在 Console。print(x)
和x
在单独执行时都会输出x
的 value,但二者是有几个细微的区别:- 通过 Source 的方式执行当前活动脚本中所有的代码时,
print(x)
会在 Console 输出x
的 value,x
则不会; - 在 function 内部使用
print(x)
,在执行 function 时会在 Console 输出x
的 value,x
则不会; - 在循环体内部使用
print(x)
会在 Console 输出x
的 value,x
则不会(具体例子将在11章节展示)。
- 通过 Source 的方式执行当前活动脚本中所有的代码时,
-
cat(..., sep = " ", fill = FALSE, labels = NULL)
,将输入的一个或多个 object 拼接后输出在 Console。可选 argument:-
sep = " "
,拼接时用来分隔各项的字符串。
-
cat("The correlation between a and b is", 0.6)
#> The correlation between a and b is 0.6
cat("The correlation between a and b is", 0.6, sep = "_")
#> The correlation between a and b is_0.6
cat("The correlation between a and b is\n", 0.6)
#> The correlation between a and b is
#> 0.6
cat("The correlation between a and b is", rep("+", 100), 0.6, rep("+", 100),
sep = "")
#> The correlation between a and b is++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++0.6++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10.4.7 Head and tail
head(x, n = 6L)
和tail(x, n = 6L)
,在Console
输出x
的前 6 或后 6 个元素(x
为vector
)/行(x
为matrix
或data.frame
)。可选argument
:
-
n
表示输出的个/行数,默认为 6。
m1 <- matrix(1:100, 10, 10)
head(m1)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 1 11 21 31 41 51 61 71 81 91
#> [2,] 2 12 22 32 42 52 62 72 82 92
#> [3,] 3 13 23 33 43 53 63 73 83 93
#> [4,] 4 14 24 34 44 54 64 74 84 94
#> [5,] 5 15 25 35 45 55 65 75 85 95
#> [6,] 6 16 26 36 46 56 66 76 86 96
tail(m1)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [5,] 5 15 25 35 45 55 65 75 85 95
#> [6,] 6 16 26 36 46 56 66 76 86 96
#> [7,] 7 17 27 37 47 57 67 77 87 97
#> [8,] 8 18 28 38 48 58 68 78 88 98
#> [9,] 9 19 29 39 49 59 69 79 89 99
#> [10,] 10 20 30 40 50 60 70 80 90 100
10.4.8 Continuous to discrete
cut(x, breaks)
-
x
: a numeric vector which is to be converted to a factor by cutting. -
breaks
: either a numeric vector of two or more unique cut points or a single number (greater than or equal to 2) giving the number of intervals into which x is to be cut.
cut(1:10, breaks = c(0, 3, 6, 10))
#> [1] (0,3] (0,3] (0,3] (3,6] (3,6] (3,6] (6,10] (6,10]
#> [9] (6,10] (6,10]
#> Levels: (0,3] (3,6] (6,10]
![](images/20215311_Acta_Psychologica_Sinica_Table1.png)
# Simulate the demographic data reported in
# http://journal.psych.ac.cn/xlxb/article/2021/0439-755X/0439-755X-53-11-1215.shtml
Income <- c(sample(11999, 122),
sample(12000:35999, 332),
sample(36000:100000, 219))
Income <- c(Income, NA, NA)
is_lost <- rep(1, length(Income))
is_lost[c(sample(122, 78),
sample(123:454, 200),
sample(456:673, 140))] <- 0
is_lost[c(length(Income) - 1, length(Income))] <- NA
data_xb <- data.frame(Income, is_lost)
head(data_xb)
#> Income is_lost
#> 1 3756 1
#> 2 8942 1
#> 3 6500 0
#> 4 10643 0
#> 5 5499 1
#> 6 8075 0
data_xb$Income <- cut(data_xb$Income, c(0, 11999, 35999, 100000),
labels = c("¥0-11,999", "¥12,000-35,999",
"¥36,000及以上"))
data_xb$is_lost <- factor(data_xb$is_lost, levels = c(1, 0), labels = c("保留样本", "流失样本"))
as.matrix(table(data_xb))
#> is_lost
#> Income 保留样本 流失样本
#> ¥0-11,999 44 78
#> ¥12,000-35,999 132 200
#> ¥36,000及以上 79 140
10.4.9 Built-in constants
R 中内置有如下常量:
pi
#> [1] 3.141593
LETTERS
#> [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N"
#> [15] "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z"
letters
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n"
#> [15] "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
month.abb
#> [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep"
#> [10] "Oct" "Nov" "Dec"
month.name
#> [1] "January" "February" "March" "April"
#> [5] "May" "June" "July" "August"
#> [9] "September" "October" "November" "December"
10.5 Precedence of operators (optional)
目前学过的 operators 可以大致归为以下几类:
类 | 包括 | 如何查看帮助 |
---|---|---|
subsetting (取子集) |
$ @ [[]] []
|
?`$` ($ 可替换为任意一个subsetting operator )或 ?Extract
|
Colon (分号) |
: |
?`:` 或 ?Colon
|
Arithmetic (算术) |
+ , - , * , / , ^ , %% , %/% , %*%
|
?`+` (+ 可替换为任意一个 Arithmetic operator) 或?Arithmetic ,?matmult
|
Relational (关系) |
> , < , <= , >= , == , !=
|
?`>` (> 可替换为任意一个 Relation operator)或 ?Comparison
|
Logical (逻辑) |
! , & , && , | , ||
|
?`!` (! 可替换为任意一个 Logical operator)或 ?Logic
|
Assignment (分配) |
<- |
?`<-` 或 ?assignOps
|
注意:` `
为反单引号,当某个 name 本身是非法字符(如已经定义的 operator)或者违背 name 命名规则时,就需要加反单引号来标识,否则会被当作是语句直接执行。
以上各 operator 在同一个语句中执行时是有优先顺序(precedence)的,就好比是加减乘除运算有优先顺序一样,同一个式子中先算乘除后算加减。 R 中各 operator 的优先顺序如下:
![](images/operation%20precedence.png)
如果没有注意优先顺序,容易出现代码的执行结果和预期不一致的情况,例如:
a <- runif(10)
a
# 把最大值最小值所在位置找出来
position <- 1:length(a)[as.logical(a == max(a) + a == min(a))]
position
#> Error: <text>:4:52: unexpected '=='
#> 3: # 把最大值最小值所在位置找出来
#> 4: position <- 1:length(a)[as.logical(a == max(a) + a ==
#> ^
如果需要保证低优先度的操作被完整执行,不受高优先度代码的影响,需要使用()
把低优先度的操作包起来:
a <- runif(10)
a
#> [1] 0.6930702 0.2492392 0.2016012 0.4639661 0.6908769
#> [6] 0.2595410 0.4797703 0.4438720 0.3964906 0.1242069
# 把最大值最小值所在位置找出来
position <- (1:length(a))[as.logical((a == max(a)) + (a == min(a)))]
position
#> [1] 1 10
更多有关 operator 优先顺序的内容请使用?Syntax
查看。
如果在实际编程过程中,如果不能准确记住各 operator 之间的优先顺序也不要紧。可以在不确定的时候,将不确定的代码单独拿出来执行一下,确保和自己预期的结果一致,如果发现不一致,就说明存在低优先度的操作但没有用()
的情况,然后再去查看问题到底出在哪一个操作。
10.6 Recap
常用操作 | operators 或 functions |
---|---|
基本数学运算 |
operator :+ - * / ^ %% %/% %*% 极值: max() min() 求和: sum() rowSums() colSums() 均值: mean() rowMeans() colMeans() 求积: prod() 取整: round() ceiling() floor() trunc() 自然指数和对数: exp() log() 开根号: sqrt() 三角函数: sin() cos() tan() 绝对值: abs() 符号: sign() 转置: t()
|
关系和逻辑 | 关系operator :> < >= <= == != 逻辑 operator :& && | || !
|
定位、匹配和排序 | 定位:which() 匹配: %in% 排序: sort() order()
|
其他 | 合并:c() cbind() rbind() 个数: length() nrow() 或 NROW() ncol() 或 NCOL() nchar() 生成序列: : seq() rep() 随机抽样: sample() 拼接字符: paste() 输出: print() cat() “展露头脚”: head() tail() 内置常量: pi letters LETTERS month.abb month.name 连续变离散: cut()
|
- 大多数 operators 和 functions 支持 recycling rule,(详见@ref(byrow-recycling);
-
round()
的规则是 4 舍 6 入,逢 5 成双; -
&
(|
)和&&
(||
)的区别是前者匹配所有位置上的元素对,后者只匹配第一个位置; - Relational operator 和 logical operator 常搭配在一起,用于按照指定条件 subsetting;
-
cbind()
和rbind()
的默认输出结果是 matrix,只有拼接的 object 中有 data.frame 时,输出结果才是 data.frame; - 常用
:
、seq()
、rep()
和sample()
产生位置索引,实现快速抽取和复制数据的目的; - 通过 Source 执行活动脚本的全部代码时,要输出内容至 Console 需使用
print()
或cat()
; - operators 间在执行上有优先顺序,同时使用多种 operators 时要注意检查结果是否符合预期;
- 使用
()
包裹住低优先度的代码可以保证这部分代码被完整执行。