数学函数
abs(x) 绝对值
sqrt(x) 平方根
ceiling(x) 向上取整函数
floor(x) 向下取整函数
trunc(x) 向0截取
round(x) 四舍五入函数
signif(x) 截取有效位
cos(x),sin(x),tan(x)
acos(x),asin(x),atan(x)
cosh(x),sinh(x),tanh(x)
acosh(x),asinh(x),atanh(x)
log(x),log10(x)
exp(x) 指数函数
当这些函数被应用于数值向量、矩阵或数据框时,它们会作用于每一个独立的值。
统计函数
mean(x) 平均数
median(x) 中位数
sd(x) 标准差
var(x) 方差
mad(x) 绝对中位数
quantile(x) 分位数
range(x) 求值域
sum(x) 求和
min(x) 最小值
max(x) 最大值
scale(x) 对数据进行中心化或标准化
> x <- c(1, 2, 3, 4, 5, 6, 7, 8)
> mean(x)
[1] 4.5
> sd(x)
[1] 2.44949
> n <- length(x)
> meanx <- sum(x)/n
> css <- sum((x - meanx)^2)
> sdx <- sqrt(css/(n - 1))
> meanx
[1] 4.5
> sdx
[1] 2.44949
数据的标准化
默认情况下,函数scale()对矩阵或数据框的指定列进行均值为 0、标准差为 1 的标准化。
要对每一列进行任意均值和标准差的标准化:
newdata <- scale(mydata)*SD + M
其中的M是想要的均值,SD为想要的标准差。
要对指定列而不是整个矩阵或数据框进行标准化:
newdata <- transform(mydata, myvar = scale(myvar)*10+50)
将变量myvar标准化为均值 50、标准差为 10 的变量。
概率函数
概率函数通常用来生成特征已知的模拟数据,以及在用户编写的统计函数中计算概率值。
概率函数形如:
[dpqr]distribution_abbreviation()
d 密度函数
p 分布函数
q 分位数函数
r 生成随机数(随机偏差)
常用的概率函数:
beta Beta分布
binom 二项分布
cauchy 柯西分布
chisq (非中心)卡方分布
exp 指数分布
f F分布
gamma Gamma分布
geom 几何分布
hyper 超几何分布
lnorm 对数正态分布
logis Logistic分布
multinom 多项分布
nbinom 负二项分布
norm 正态分布
pois 泊松分布
signrank Wilcoxon符号秩分布
t t分布
unif 均匀分布
weibull Weibull分布
wilcox Wilcoxon秩和分布
> x <- pretty(c(-3, 3), 30)
> y <- dnorm(x)
> plot(x, y, type="l", xlab="Normal Deviate", ylab="Density", yaxs="i")
> pnorm(1.96)
[1] 0.9750021
> qnorm(.9, mean=500, sd=100)
[1] 628.1552
> rnorm(50, mean=50, sd=10)
[1] 50.90701 23.30479 49.26953 43.69341 58.33219 74.55983 48.87788 50.07223
[9] 51.13661 52.04896 49.29812 60.97722 68.27475 51.88737 49.31403 48.46568
[17] 47.35525 57.26836 54.03473 44.85644 61.34435 59.34282 71.21762 55.63532
[25] 49.81657 46.91496 38.88280 62.15051 40.71857 58.62943 49.45462 48.82537
[33] 38.55603 28.34087 64.75731 52.24712 48.94070 52.32623 61.49825 31.68802
[41] 45.84526 57.47583 52.81701 61.53104 51.57661 56.20224 47.86015 53.98346
[49] 54.56368 56.29681
设定随机种子
在每次生成伪随机数的时候,函数都会使用一个不同的种子,因此也会产生不同的结果。你可以通过函数set.seed()显式指定这个种子,让结果可以重现(reproducible)。
> runif(5)
[1] 0.9505711 0.1176140 0.7294812 0.8418611 0.8859856
> runif(5)
[1] 0.65070547 0.03970935 0.17168482 0.99797468 0.91804578
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
生成多元正态数据
在模拟研究和蒙特卡洛方法中,经常需要获取来自给定均值向量和协方差阵的多元正态分布的数据。MASS包中的mvrnorm()函数可以让这个问题变得很容易。其调用格式为:
mvrnorm(n, mean, sigma)
n是想要的样本大小,mean为均值向量,sigma是方差-协方差矩阵(或相关矩阵)。
> library(MASS)
载入程辑包:‘MASS’
The following object is masked from ‘package:dplyr’:
select
Warning message:
程辑包‘MASS’是用R版本3.6.3 来建造的
> options(digits=3)
> set.seed(1234)
> mean <- c(230.7, 146.7, 3.6)
> sigma <- matrix(c(15360.8, 6721.2, -47.1, 6721.2, 4700.9, -16.5, -47.1, -16.5, 0.3), nrow=3, ncol=3)
> mydata <- mvrnorm(500, mean, sigma)
> mydata <- as.data.frame(mydata)
> names(mydata) <- c("y", "x1", "x2")
> dim(mydata)
[1] 500 3
> head(mydata, n=10)
y x1 x2
1 98.8 41.3 3.43
2 244.5 205.2 3.80
3 375.7 186.7 2.51
4 -59.2 11.2 4.71
5 313.0 111.0 3.45
6 288.8 185.1 2.72
7 134.8 165.0 4.39
8 171.7 97.4 3.64
9 167.2 101.0 3.50
10 121.1 94.5 4.10
R 中的概率函数允许生成模拟数据,这些数据是从服从已知特征的概率分布中抽样而得的。
字符处理函数
nchar(x) 计算字符数量
substr(x, stop, start) 提取或替换一个字符向量中的子串
grep(pattern, x, ignore, case=FALSE, fixed=FALSE) 搜索某种模式。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。返回值为匹配的下标。
sub(pattern, replacement, x, ignore.case=FALSE, fixed=FALSE) 在x中搜索pattern,并以文本replacement将其替换。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。
strsplit(x, split, fixed=FALSE) 在split处分割字符向量x中的元素。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。
paste(..., sep="") 连接字符串,分隔符为sep。
toupper(x) 大写转换
tolower(x) 小写转换
将函数应用于矩阵和数据框
> a <- 5
> sqrt(5)
[1] 2.24
> b <- c(1.243, 5.654, 2.99)
> round(b)
[1] 1 6 3
> c <- matrix(runif(12), nrow=3)
> c
[,1] [,2] [,3] [,4]
[1,] 0.9636 0.216 0.289 0.913
[2,] 0.2068 0.240 0.804 0.353
[3,] 0.0862 0.197 0.378 0.931
> log(c)
[,1] [,2] [,3] [,4]
[1,] -0.0371 -1.53 -1.241 -0.0912
[2,] -1.5762 -1.43 -0.218 -1.0402
[3,] -2.4511 -1.62 -0.972 -0.0710
> mean(c)
[1] 0.465
> mydata <- matrix(rnorm(30), nrow=6)
> mydata
[,1] [,2] [,3] [,4] [,5]
[1,] 0.459 1.203 1.234 0.591 -0.281
[2,] -1.261 0.769 -1.891 -0.435 0.812
[3,] -0.527 0.238 -0.223 -0.251 -0.208
[4,] -0.557 -1.415 0.768 -0.926 1.451
[5,] -0.374 2.934 0.388 1.087 0.841
[6,] -0.604 0.935 0.609 -1.944 -0.866
> apply(mydata, 1, mean)
[1] 0.641 -0.401 -0.194 -0.136 0.975 -0.374
> apply(mydata, 2, mean)
[1] -0.478 0.777 0.148 -0.313 0.292
> apply(mydata, 2, mean, trim=0.2)
[1] -0.516 0.786 0.386 -0.255 0.291
本例中,截尾均值基于中间 60% 的数据,最高和最低 20% 的值均被忽略。
数据处理难题的一套解决方案
> options(digits=2)
> Student <- c("John Davis", "Angela Williams", "Bullwinkle Moose", "David Jones", "Janice Markhammer", "Cheryl Cushing", "Reuven Ytzrhak", "Greg Knox", "Joel England", "Mary Rayburn")
> Math <- c(502, 600, 412, 358, 495, 512, 410, 625, 573, 522)
> Science <- c(95, 99, 80, 82, 75, 85, 80, 95, 89, 86)
> English <- c(25, 22, 18, 15, 20, 28, 15, 30, 27, 18)
> roster <- data.frame(Student, Math, Science, English, stringsAsFactors=FALSE )
> roster
Student Math Science English
1 John Davis 502 95 25
2 Angela Williams 600 99 22
3 Bullwinkle Moose 412 80 18
4 David Jones 358 82 15
5 Janice Markhammer 495 75 20
6 Cheryl Cushing 512 85 28
7 Reuven Ytzrhak 410 80 15
8 Greg Knox 625 95 30
9 Joel England 573 89 27
10 Mary Rayburn 522 86 18
由于数学、科学和英语考试的分值不同(均值和标准差相去甚远),在组合之前需要先让它们变得可以比较。一种方法是将变量进行标准化,这样每科考试的成绩就都是用单位标准差来表示,而不是以原始的尺度来表示了。
> z <- scale(roster[, 2:4])
> z
Math Science English
[1,] 0.013 1.078 0.587
[2,] 1.143 1.591 0.037
[3,] -1.026 -0.847 -0.697
[4,] -1.649 -0.590 -1.247
[5,] -0.068 -1.489 -0.330
[6,] 0.128 -0.205 1.137
[7,] -1.049 -0.847 -1.247
[8,] 1.432 1.078 1.504
[9,] 0.832 0.308 0.954
[10,] 0.243 -0.077 -0.697
attr(,"scaled:center")
Math Science English
501 87 22
attr(,"scaled:scale")
Math Science English
86.7 7.8 5.5
> score <- apply(z, 1, mean)
> roster <- cbind(roster, score)
> roster
Student Math Science English score
1 John Davis 502 95 25 0.56
2 Angela Williams 600 99 22 0.92
3 Bullwinkle Moose 412 80 18 -0.86
4 David Jones 358 82 15 -1.16
5 Janice Markhammer 495 75 20 -0.63
6 Cheryl Cushing 512 85 28 0.35
7 Reuven Ytzrhak 410 80 15 -1.05
8 Greg Knox 625 95 30 1.34
9 Joel England 573 89 27 0.70
10 Mary Rayburn 522 86 18 -0.18
> y <- quantile(roster$score, c(.8, .6, .4, .2))
> y
80% 60% 40% 20%
0.74 0.44 -0.36 -0.89
> roster$grade[score>=y[1]] <- "A"
> roster$grade[score<y[1] & score>=y[2]] <- "B"
> roster$grade[score<y[2] & score>=y[3]] <- "C"
> roster$grade[score<y[3] & score>=y[4]] <- "D"
> roster$grade[score<y[4]] <- "F"
> roster
Student Math Science English score grade
1 John Davis 502 95 25 0.56 B
2 Angela Williams 600 99 22 0.92 A
3 Bullwinkle Moose 412 80 18 -0.86 D
4 David Jones 358 82 15 -1.16 F
5 Janice Markhammer 495 75 20 -0.63 D
6 Cheryl Cushing 512 85 28 0.35 C
7 Reuven Ytzrhak 410 80 15 -1.05 F
8 Greg Knox 625 95 30 1.34 A
9 Joel England 573 89 27 0.70 B
10 Mary Rayburn 522 86 18 -0.18 C
> name <- strsplit((roster$Student), " ")
> name
[[1]]
[1] "John" "Davis"
[[2]]
[1] "Angela" "Williams"
[[3]]
[1] "Bullwinkle" "Moose"
[[4]]
[1] "David" "Jones"
[[5]]
[1] "Janice" "Markhammer"
[[6]]
[1] "Cheryl" "Cushing"
[[7]]
[1] "Reuven" "Ytzrhak"
[[8]]
[1] "Greg" "Knox"
[[9]]
[1] "Joel" "England"
[[10]]
[1] "Mary" "Rayburn"
> Firstname <- sapply(name, "[", 1)
> Lastname <- sapply(name, "[", 2)
> roster <- cbind(Firstname, Lastname, roster[, -1])
> roster
Firstname Lastname Math Science English score grade
1 John Davis 502 95 25 0.56 B
2 Angela Williams 600 99 22 0.92 A
3 Bullwinkle Moose 412 80 18 -0.86 D
4 David Jones 358 82 15 -1.16 F
5 Janice Markhammer 495 75 20 -0.63 D
6 Cheryl Cushing 512 85 28 0.35 C
7 Reuven Ytzrhak 410 80 15 -1.05 F
8 Greg Knox 625 95 30 1.34 A
9 Joel England 573 89 27 0.70 B
10 Mary Rayburn 522 86 18 -0.18 C
> roster[order(Lastname, Firstname),]
Firstname Lastname Math Science English score grade
6 Cheryl Cushing 512 85 28 0.35 C
1 John Davis 502 95 25 0.56 B
9 Joel England 573 89 27 0.70 B
4 David Jones 358 82 15 -1.16 F
8 Greg Knox 625 95 30 1.34 A
5 Janice Markhammer 495 75 20 -0.63 D
3 Bullwinkle Moose 412 80 18 -0.86 D
10 Mary Rayburn 522 86 18 -0.18 C
2 Angela Williams 600 99 22 0.92 A
7 Reuven Ytzrhak 410 80 15 -1.05 F
控制流
for结构语法:
for (var in seq) statement
> for (i in 1:10){
+ print("Hello")
+ }
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
while结构语法:
while (cond) statement
> while (i > 0){
+ print("Hello")
+ i <- i - 1
+ }
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
if-else结构语法:
if (cond) statement
if (cond) statement1 else statement2
> if (is.character(roster$grade)) roster$grade <- as.factor(roster$grade)
> if (!is.factor(roster$grade)) roster$grade <- as.factor(roster$grade) else print("Grade already is a factor")
[1] "Grade already is a factor"
ifelse语法结构:
ifelse(cond, statement1, statement2)
> ifelse(score>0.5, print("Passed"), print("Failed"))
[1] "Passed"
[1] "Failed"
[1] "Passed" "Passed" "Failed" "Failed" "Failed" "Failed" "Failed" "Passed" "Passed" "Failed"
> outcome <- ifelse(score > 0.5, "Passed", "Failed")
> outcome
[1] "Passed" "Passed" "Failed" "Failed" "Failed" "Failed" "Failed" "Passed" "Passed" "Failed"
switch结构语法:
switch(expr, ...)
> feelings <- c("sad", "afraid")
> for (i in feelings){
+ print(switch(i,
+ happy = "I am glad you are happy",
+ afraid = "There is nothing to fear",
+ sad = "Cheer up",
+ angry = "Calm down now"))
+ }
[1] "Cheer up"
[1] "There is nothing to fear"
用户自编函数
函数语法:
myfunction <- function(arg1, arg2, ... ){
statements
return(object)
}
函数中的对象只在函数内部使用,返回对象的数据类型是任意的,从标量到列表皆可。
编写一个函数,用来计算数据对象的集中趋势和散布情况,此函数可以选择性地给出参数统计量(均值和标准差)和非参数统计量(中位数和绝对中位差),结果以一个含名称列表的形式给出,另外可以选择是否自动输出结果。除非另外指定,否则此函数的默认行为是计算参数统计量并且不输出结果。
> mystats <- function(x, parametric=TRUE, print=FALSE){
+ if (parametric){
+ center <- mean(x)
+ spread <- sd(x)
+ } else {
+ center <- median(x)
+ spread <- mad(x)
+ }
+ if (print & parametric){
+ cat("Mean=", center, "\n", "SD=", spread, "\n")
+ } else if (print & !parametric){
+ cat("Median=", center, "\n", "MAD=", spread, "\n")
+ }
+ result <- list(center=center, spread=spread)
+ return(result)
+ }
> set.seed(1234)
> x <- rnorm(500)
> y <- mystats(x)
> y$center
[1] 0.0018
> y$spread
[1] 1
> y <- mystats(x, parametric=FALSE, print=TRUE)
Median= -0.021
MAD= 1
让用户选择输出当天日期的格式,在函数声明中为参数指定的值将作为其默认值,在函数mydate()中,如果未指定type,则long将为默认的日期格式。
> mydate <- function(type="long"){
+ switch(type,
+ long = format(Sys.time(), "%A %B %d %Y"),
+ short = format(Sys.time(), "%m-%d-%y"),
+ cat(type, "is not a recognized type\n")
+ )
+ }
> mydate("long")
[1] "星期日 十月 11 2020"
> mydate("short")
[1] "10-11-20"
> mydate()
[1] "星期日 十月 11 2020"
> mydate("medium")
medium is not a recognized type
cat()仅会在输入的日期格式类型不匹配"long"或"short"时执行。
有若干函数可以用来为函数添加错误捕获和纠正功能,可以使用函数warning()来生成一条错误提示信息,用message()来生成一条诊断信息,或用stop()停止当前表达式的执行并提示错误。