本章内容
- 数字和统计函数
- 字符处理函数
- 循环和条件执行
- 自编函数
- 数据整合与重塑
5.1 一个数据处理难题
题目详见R语言实战第一版第86页(需要的同学,公众号私信:R语言实战。小编会发连接)
5.2 数值和字符处理函数
- 数值函数(数学、统计、概率)
- 字符处理函数
5.2.1 数学函数
略
5.2.2 统计函数
函数 | 描述 |
---|---|
mean(x) | 平均数 |
median(x) | 中位数 |
sd(x) | 标准差 |
var(x) | 方差 |
mad(x) | 绝对中位差 |
quantile(x, probs) | 求分位数 |
range(x) | 求值域 |
sum(x) | 求和 |
diff(x, lag=n) | 滞后差分 |
min(x) | 求最小值 |
max(x) | 求最大值 |
scale(x, center=TRUE, scale=TRUE) | 为数据对象x按列进行中心化(center=TRUE)或标准化(center=TRUE, scale=TRUE) |
- mad:具体的mad含义可参考这里:https://blog.csdn.net/horses/article/details/78749485
- quantile(x, probs):其中x为待求分位数的数值型向量,probs为一个由[0,1]之间的概率值组成的数值向量。
- 求x的30%和84%分位点:y = quantile(x, c(0.3, 0.84))
- diff:默认的lag=1。x=c(1,5,23,29), diff(x)返回值为c(4,18,6)
数据的标准化
默认情况下,函数scale()对矩阵或数据框的指定列进行均值为0、标准差为1的标准化
如果要对每一列进行任意均值和标准差的标准化,可使用
mydate = scale(data)*SD+M
5.2.3 概率函数
分布的某一方面+概率分布
1、第一个字母表示分布的某一方面:
d = 密度函数(density)
p = 分布函数(distribution function)
q = 分位数函数(quantile function)
r = 生成随机数(随机偏差)
2、概率分布
分布名称 | 缩 写 | 分布名称 | 缩 写 |
---|---|---|---|
Beta分布 | beta | Logistic分布 | logis |
二项分布 | binom | 多项分布 | multinom |
柯西分布 | cauchy | 负二项分布 | nbinom |
(非中心)卡方分布 | chisq | 正态分布 | norm |
指数分布 | exp | 泊松分布 | pois |
F分布 | f | Wilcoxon符号秩分布 | signrank |
Gamma分布 | gamma | t分布 | t |
几何分布 | geom | 均匀分布 | unif |
超几何分布 | hyper | Weibull分布 | weibull |
对数正态分布 | lnorm | Wilcoxon秩和分布 | wilcox |
举例:runif();代表生成0到1区间上服从均匀分布的随机数。(r+unif)
5.2.4 字符处理函数
函数 | 描述 |
---|---|
substr(x, start, stop) | 提取或替换一个字符向量中的子串 x <- "abcdef" substr(x, 2, 4)返回值为"bcd" substr(x, 2, 4) <- "22222"(x将变成"a222ef") |
grep(pattern, x, ignore.case=FALSE, fixed=FASLE) | 在x中搜索某种模式。pattern可以使用正则表达式。 返回值为匹配的下标 grep("A",c("b","A","c"),fixed=TRUE)返回值为2 |
sub(pattern, replacement, x, ignore.case=FALSE, fixed=FASLE) | 在x中搜索pattern,并以文本replacement将其替换。 pattern可以使用正则表达式。 sub(''\\s",".","Hello There")返回值为Hello.There。 |
strsplit(x, split, fixed=FALSE) | 在split处分割字符向量x中的元素。 pattern可以是正则表达式或一个文本字符串 y <- strsplit("abc", "")将返回一个含有1个成分、3个元素的列表 包含的内容为"a" "b" "c" unlist(y)[2]和sapply(y, "[", 2)均会返回"b" |
sapply(y, "[", 2)的解释如下:
"["在R中作为一个函数使用
x <- 1:10
x[2]
## 2
"["(x,2)
## 2
如上例,"["(x,2)
返回向量x的第2个数
data <- list(1:10, 2:12)
sapply(data, "[", 2)
## 2 3
如上例如果数据类型为列表sapply(data, "[", 2)
就是分别取两个list里的第二个数.
5.2.5 其他实用函数
函数 | 描述 |
---|---|
cut(x, n) | 将连续型变量x分割为有着n个水平的因子 使用选项ordered_result = TRUE以创建一个有序型因子 |
pretty(x, n) | 创建美观的分割点。通过选取n+1个等间距的取整值,将一个连续型变量x分割为n个 区间。绘图中常用 |
cat(..., file = "myfile", append = FALSE) | 连接...中的对象,并将其输出到屏幕上或文件中(如果声明了一个的话) firstname <- c("Jane") cat("Hello" ,firstname) ## Hello Jane |
5.2.6 将函数应用于矩阵或数据框
函数apply()
apply(x, MARGIN, FUN, ...)
x为数据对象,MARGIN是维度的下标,FUN是由你指定的函数,而...则包括了任何想传递给FUN的参数。在矩阵或数据框中,MARGIN=1表示行,MARGIN=2表示列。
set.seed(1234)
mydata <- matrix(rnorm(30), nrow = 6)
mydata
## [,1] [,2] [,3] [,4] [,5]
## [1,] -1.2070657 -0.5747400 -0.77625389 -0.8371717 -0.6937202
## [2,] 0.2774292 -0.5466319 0.06445882 2.4158352 -1.4482049
## [3,] 1.0844412 -0.5644520 0.95949406 0.1340882 0.5747557
## [4,] -2.3456977 -0.8900378 -0.11028549 -0.4906859 -1.0236557
## [5,] 0.4291247 -0.4771927 -0.51100951 -0.4405479 -0.0151383
## [6,] 0.5060559 -0.9983864 -0.91119542 0.4595894 -0.9359486
# trim指定截尾,=0.2代表丢弃最大的20%和最小的20%的数据
apply(mydata, 1, FUN = mean, trim = 0.2)
## -0.76904861 -0.06824793 0.55611267 -0.80145982 -0.31095962 -0.46251819
注意:
1、apply()可把函数应用到数组的某个维度上
2、而lapply()和sapply()则可将函数应用到列表(list)上。
5.3 处理5.1中的难题
将学生的各科考试成绩组合为单一的成绩衡量指标、基于相对名次(前20%,下20%,等等)给出从A到E的评分、根据学生姓氏和名字的首字母对花名册进行排序。
#1、 创建要分析的数据框,限定输出小数点后2位
options(stringsAsFactors = FALSE, 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)
#2、标准化数据(数学、科学和英语的分值不同(均值和标准差相差太多),我们要在组合前需要让他们变得可以比较。我们采用将变量标准化,这样所有科#目的成绩都是m=0,sd=1,就可以比较了)
scaled <- scale(roster[,2:4])
score_scaled <- apply(scaled, 1, mean)
roster <- cbind(roster, score_scaled)
#3、求分数区间,划分成绩评分
diff <- quantile(score_scaled, c(0.8, 0.6, 0.4, 0.2))
roster <- within(roster,{
grade <- NA;
grade[score_scaled >= diff[1]] <- "A";
grade[score_scaled >= diff[2] & score_scaled < diff[1]] <- "B";
grade[score_scaled >= diff[3] & score_scaled < diff[2]] <- "C";
grade[score_scaled >= diff[4] & score_scaled < diff[3]] <- "D";
grade[score_scaled < diff[4]] <- "E"
})
#4、提取姓名
name <- strsplit(roster[,1],' ')
firstnames <- sapply(name, '[', 1)
lastnames <- sapply(name, '[', 2)
roster <- cbind(firstnames, lastnames, roster[,-1])
#5、按姓和名排序
roster <- roster[order(lastnames,firstnames),]
roster
## firstnames lastnames Math Science English score_scaled 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 E
## 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 E
5.4 控制流
5.4.1重复和循环
1、for结构
for(var in seq) statement
2、while结构
while(cond) statement
5.4.2 条件执行
1、if-else结构
if (cond) statement1 else statement2
2、ifelse结构
ifelse(cond, statement1, statement2)
3、switch结构
switch(expr, ...)
其中的...表示与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 用户自编函数
下面使用switch编写一个函数,可以让用户选择输出当天日期格式
mydata <- 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.")
)
}
5.6 整合与重构
5.6.1 转置
t()
5.6.2 整合数据
aggregate(x, by, FUN)
其中x是待折叠的数据对象,by是一个变量名组成的列表,这些变量将被去掉以形成新的观测,而FUN则是用来计算描述性统计量的标量函数,它将被用来计算新观测中的值。
options(digits=3)
aggdata <-aggregate(mtcars,
by=list(mtcars$cyl,mtcars$gear),
FUN=mean, na.rm=TRUE)
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
在结果中,Group.1表示汽缸数量(4、6或8),Group.2代表挡位数(3、4或5)。举例来说,拥有4个汽缸和3个挡位车型的每加仑汽油行驶英里数(mpg)均值为21.5。
注意:by中的变量必须在一个列表中(即使只有一个变量)。你还可以自定义列的名称如:by=list(Cylinders=cyl, Gears=gear
5.6.3 宽数据集和长数据集之间的转换
不同的数据格式,适用于不同的数据分析。虽然大多数R函数使用宽格式的数据框,但有些函数要求数据采用长格式。
使用tidyr包中的gather()函数可以实现将宽数据转换为长数据。
install.packages("tidyr")
library(tidyr)
longdata <- gather(widedata, key, value, variable list)
- widedata为待转换的数据框
- key指定要用于变量列的名称(在本例中为“variable”)
- value指定用于值列的名称(本例中为“LifeExp”)
- variable list指定要堆叠的变量(本例为LExp1990, LExp2000, LExp2010)
data_wide <- data.frame(ID = c("AU", "CN", "PRK"),
Country = c("Australia", "China", "North Korea"),
LExp1990 = c(76.9, 69.3, 69.9),
LExp2000 = c(79.6, 72.0, 65.3),
LExp2010 = c(82.0, 75.2, 69.6))
data_wide
## ID Country LExp1990 LExp2000 LExp2010
## 1 AU Australia 76.9 79.6 82.0
## 2 CN China 69.3 72.0 75.2
## 3 PRK North Korea 69.9 65.3 69.6
data_long <- gather(data_wide, key="Variable", value="Life_Exp",
c(LExp1990, LExp2000, LExp2010))
data_long
## ID Country Variable Life_Exp
## 1 AU Australia LExp1990 76.9
## 2 CN China LExp1990 69.3
## 3 PRK North Korea LExp1990 69.9
## 4 AU Australia LExp2000 79.6
## 5 CN China LExp2000 72.0
## 6 PRK North Korea LExp2000 65.3
## 7 AU Australia LExp2010 82.0
## 8 CN China LExp2010 75.2
## 9 PRK North Korea LExp2010 69.6
spread() 函数可以将长数据转换为宽数据。
widedata <- spread(longdata, key, value)
- longdata是待转换的数据框
- Key是包含变量名的列
- Value是包含变量值的列
data_wide <- spread(data_long, key = "Variable", value = "Life_Exp")
data_wide
## ID Country LExp1990 LExp2000 LExp2010
## 1 AU Australia 76.9 79.6 82.0
## 2 CN China 69.3 72.0 75.2
## 3 PRK North Korea 69.9 65.3 69.6
小结
- 基于R,包含数百个数学、统计和概率函数,这些函数对于操作数据很有用。它们可以广泛应用于数据对象,包括向量、矩阵和数据框。
- 掌握重复和循环以及条件执行。
- 在进行进一步分析之前,通常需要对数据进行整合或重构。