本章内容
数学和统计函数
字符处理函数
循环和条件执行
自编函数
数据整合与重塑
5.1 一个数据处理难题
均值和标准差相去甚远,求平均值没有意义。变换为可比较的单元。巧妙利用数值和字符处理函数。
5.2 数值和字符处理函数
数据处理基石的函数:数值(数学、统计、概率)函数和字符处理函数,应用于矩阵和数据框。
5.2.1 数学函数
对数据做变换是这些函数的一个主要用途。当应用于数值向量、矩阵或数据框时,会作用于每一个独立的值
。[P86]
abs(x) # 绝对值
sqrt(x) # 平方根
ceiling(x) # 不小于x的最小整数
floor(x) # 不大于x的最大整数
log(x, base = n) # 对x取以n为底的对数
log(x)
log10(x)
log(10)
log10(10)
exp(x) # 指数函数
5.2.2 统计函数
许多函数都有影响输出结果的可选参数。比如:
y <- mea(x)
z <- mean(x, trim = 0.05, na.rm = TRUE)
y
提供了算术平均数,z
提供了截尾平均数,即丢弃了最大5%和最小5%的数据和所有缺失值后的算术平均数。
mean(x)
median(x)
sd(x)
var(x)
mad(x)
quantile(x, probs)
range(x)
sum(x)
diff(x, lag = n)
min(n)
max(x)
scale(x, center = TRUE, scale = TRUE) #为数据对象x按列进行中心化或标准化
##均值和标准差的计算
x <- c(1:8)
#简洁的方式
mean(x)
sd(x)
#冗长的方式
n <- length(x)
meanx <- sum(x)/n
css <- sum((x - meanx)^2)
sdx <- sqrt(css / (n-1))
meanx
sdx
数据的标准化
默认情况下,函数scale()
对矩阵或数据框的指定列
进行均值为0、标准差为1
的标准化:
newdata <- scale(mydata)
要对每一列进行任意均值和标准差的标准化,可以使用如下的代码:
newdata <- scale(mydata)*SD + M
其中的M是想要的均值,SD为想要的标准差。在非数值型
的列上使用scale()函数将会报错
。要 对指定列
而不是整个矩阵或数据框进行标准化,你可以使用这样的代码:
newdata <- transform(mydata, myvar = scale(myvar)*10 +50)
此句将变量myvar标准化为均值50、标准差为10的变量。
5.2.3 概率函数
概率函数通常用来生产特征已知的模拟数据,以及在用户编写的统计函数中计算概率值。
- 设定随机数种子
在每次生成伪随机数的时候,函数都会使用一个不同的种子,因此也会产生不同的结果。set.seed()
runif(5) #重复两次
set.seed(1234)
runif(5)
- 生成多元正态数据
在模拟研究和蒙特卡洛方法中,你经常要获取来自给定均值向量和协方差阵的多元正态分布的数据。MASS包中的mvnorm()函数可以让这个问题变得很容易。
mvnorm(n, mean, siga)
5.2.4 字符处理函数
字符处理函数可以从文本型数据中抽取信息,或者为打印输出和生成报告重设文本的格式。
正则表达式(英语:Regular Expression,常简写为regex、regexp或RE),又称正则表示式、正则表示法、规则表达式、常规表示法,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串、。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
5.2.5 其他实用函数
下列函数对于数据管理和处理同样非常实用。
length(x) #对象x的长度
seq(from, to , by) #生成一个序列
rep(x, n) #将x重复n次
cut(x, n) #将连续型变量x分割为有着n个水平的因子
#使用选项ordered_result = TRUE以创建一个有序型因子
pretty(x, n) #创建美观的分割点。通过选取n+1个等间距的取整值,将一个连续型变量x分割为n个 区间。绘图中常用
cat(..., file = "filename", append = F) #连接...中的对象,并将其输出到屏幕上或文件中(如果声明了一个的话)
注:\n
表示新行,\t
表示制表符,\'
表示单引号,\b
表示退格。(键入?quotes
了解更多)
5.2.6 将函数应用于矩阵和数据框
R函数的诸多有趣特性之一,就是它们可以应用到一系列的数据对象上,包括标量、向量、 矩阵、数组和数据框。
> a <- 5
> sqrt(5)
[1] 2.236068
> 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.7699015 0.61823636 0.820176206 0.6085722
[2,] 0.7128397 0.05048374 0.009614496 0.7698180
[3,] 0.3033602 0.04321880 0.102491504 0.6605425
> log(c)
[,1] [,2] [,3] [,4]
[1,] -0.2614926 -0.4808844 -0.1982361 -0.4966397
[2,] -0.3384987 -2.9861040 -4.6444833 -0.2616011
[3,] -1.1928344 -3.1414796 -2.2779754 -0.4146939
> mean(c) #矩阵c求均值的结果为一个标量(0.444)。函数mean()求得的是 矩阵中全部12个元素的均值。
[1] 0.4557713
apply()函数,可将一个任意函数“应用”到矩阵、数组、数据框的任何维度上。
apply(x, MARGIN, FUN, ...)
MARGIN=1表示行,MARGIN=2表示列。
> mydata <- matrix(rnorm(30), nrow = 6) #生成了一个包含正态随机数的6×5矩阵
> mydata
[,1] [,2] [,3] [,4] [,5]
[1,] -0.7826228 -1.1176011 -0.3271264 -0.80825957 -0.9345593
[2,] 0.5092959 0.2340028 -2.2632252 -0.51215317 0.6303857
[3,] -1.4899391 0.3161516 0.2855605 -1.80397184 0.7607600
[4,] -0.3191793 0.3707686 0.9684286 0.04062997 -0.5116228
[5,] -0.2379111 0.8775886 0.8673066 2.63601650 1.0019075
[6,] 1.6186229 -1.7683235 1.3781350 -1.61599923 -0.3833922
> apply(mydata, 1, mean) #计算6行的均值
[1] -0.7940338 -0.2803388 -0.3862878 0.1098050 1.0289816 -0.1541914
> apply(mydata, 2, mean) #计算5列的均值
[1] -0.11695557 -0.18123552 0.15151317 -0.34395622 0.09391315
> apply(mydata, 2, mean, trim = 0.2) #计算每列的截尾均值
[1] -0.20760431 -0.04916954 0.44854232 -0.72394550 0.12403268
5.3 数据处理难题的一套解决方案
见P96。
瞧!小事一桩!
5.4 控制流
- 语句(statement)是一条单独的R语句或一组复合语句。(包含在花括号{ } 中的一组R语 句,使用分号分隔);
- 条件(cond)是一条最终被解析为真(TRUE)或假(FALSE)的表达式;
- 表达式(expr)是一条数值或字符串的求值语句。
- 序列(seq)是一个数值或字符串函数。
5.4.1 重复和循环
for结构
for循环重复地执行一个语句,直到某个变量的值不再包含在序列seq中为止。
for (var in seq) statement
for (i in 1:10) print("Hello")
while结构
while循环重复地执行一个语句,直到条件不为真为止。
while (cond) statement
> i <- 10
> while(i > 0) {print("Hello"); i <- 1-1}
[1] "Hello"
> while(i > 0) {print("Hello"); i <- i-1}
> i <- 10
> 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"
5.4.2 条件执行
在条件执行结构中, 一条或一组语句仅在满足一个指定条件时执行。 条件执行结构包括 if-else、ifelse和switch。
- if-else结构
if (cond) statement
if (cond) statement else statement2
- ifelse结构
ifelse (cond, statement1, statement2)
- swtich结构
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"
5.5 用户自编函数
一个函数的结构看起来大致如此:
myfunction <- function(arg1, arg2, ...) {statements return(object)}
假设你想编写一个函数,用来计算数据对象的集中趋势和散布情况。此函数应当可以选择性地给出参数统计量(均值和标准差)和非参数统计量(中位数和绝对中位差)。结果应当以一个 含名称列表的形式给出。另外,用户应当可以选择是否自动输出结果。除非另外指定,否则此函 数的默认行为应当是计算参数统计量并且不输出结果。
mystats <- function(x, parametric = T, print = F) {
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")
}
results <- list(center = center, spread = spread)
return(results)
}
set.seed(1234)
x <- rnorm(500)
y <- mystats(x)
y <- mystats(x, parametric = F, print = T)
5.6 整合与重构
R中提供了许多用来整合(aggregate)和重塑(reshape)数据的强大方法。本节主要使用mtcars
数据集。请参阅help(mtcars)
。
5.6.1 转置
t()
反转行和列
5.6.2 整合数据
在R中使用一个或多个by变量和一个预先定义好的函数来折叠(collapse)数据是比较容易的。
aggregate(x, by, FUN)
其中x是待折叠的数据对象,by是一个变量名组成的列表,这些变量将被去掉以形成新的观测, 而FUN则是用来计算描述性统计量的标量函数,它将被用来计算新观测中的值。
> options(digits = 3)
> attach(mtcars)
> aggdata <- aggregate(x = mtcars, by = list(cyl, gear), FUN = mean, na.rm = T)
> aggdata
Group.1 Group.2 mpg cyl disp hp drat wt qsec vs am gear carb
1 4 3 21.5 4 120 97 3.70 2.46 20.0 1.0 0.00 3 1.00
2 6 3 19.8 6 242 108 2.92 3.34 19.8 1.0 0.00 3 1.00
3 8 3 15.1 8 358 194 3.12 4.10 17.1 0.0 0.00 3 3.08
4 4 4 26.9 4 103 76 4.11 2.38 19.6 1.0 0.75 4 1.50
5 6 4 19.8 6 164 116 3.91 3.09 17.7 0.5 0.50 4 4.00
6 4 5 28.2 4 108 102 4.10 1.83 16.8 0.5 1.00 5 2.00
7 6 5 19.7 6 145 175 3.62 2.77 15.5 0.0 1.00 5 6.00
8 8 5 15.4 8 326 300 3.88 3.37 14.6 0.0 1.00 5 6.00
在使用aggregate()函数的时候,by中的变量必须在一个列表中(即使只有一个变量)。
5.6.3 reshape2包
reshape包是一套重构和整合数据集的绝妙的万能工具。有点难度!
数据融合(melt)
和重铸(cast)
- 融合
> ID = c("1", "1", "2", "2")
> Time = c("1", "2", "1","2")
> X1 = c(5, 3, 6, 2)
> X2 = c(6, 5, 1, 4)
> mydata = data.frame(ID, Time, X1, X2)
> mydata
ID Time X1 X2
1 1 1 5 6
2 1 2 3 5
3 2 1 6 1
4 2 2 2 4
> library(reshape2)
> md <- melt(mydata, id = c("ID", "Time"))
> md
ID Time variable value
1 1 1 X1 5
2 1 2 X1 3
3 2 1 X1 6
4 2 2 X1 2
5 1 1 X2 6
6 1 2 X2 5
7 2 1 X2 1
8 2 2 X2 4
必须指定要唯一确定每个测量所需的变量(ID和Time),而表示测量变量名的变量(X1 或X2)将由程序为你自动创建。
- 重塑
newdata <- dcast(md, formula, fun.aggregate)
其中的md为已融合的数据,formula描述了想要的最后结果,而FUN是(可选的)数据整合函数。
5.7 小结
处理数据的数学、统计和概率函数
函数应用于向量、矩阵和数据框
控制流结构:循环重复,条件
自定义函数
折叠、整合以及重构数据