r语言 悲观剪枝_R语言实战(5) ——高级数据管理

往期回顾:

R语言实战(1)——R语言介绍

R语言实战(2)——创建数据集

R语言实战(3)——图形初阶

R语言实战(4) ——数据管理

本期是我们推出《R语言实战》赠书活动的最后一天啦!   

只要你在本文公众号的R语言实战系列的第三期--R语言实战(3) ——图形初阶留言板后台留言,前五名留言点赞次数最多的,将会获得《R语言实战》正版书籍哦,心动不如行动,赶紧转发朋友圈让更多朋友为你的留言点赞吧!!

引言:在第4章,我们学习了R中基本的数据集处理方法,本章我们学习一些高级话题。首先,我们将简单学习R中的多种数学、统计和字符处理函数。接下来,我们将简略地学习控制流的概念及基本语法。最后,我们将了解数据的整合和概述方法,以及数据集的重塑和重构方法。(后台回复“R语言实战”即可获取二维码加入R语言实战学习讨论群。)

5-1   一个数据处理难题

假设有一组学生参加了数学、科学和英语考试。我们需要给所有学生确定一个单一的成绩衡量指标以及把前20%的学生评定为A,后面20%的学生评定为B,还需要按字母顺序对学生排序。这要如何操作呢?

表5-1  学生成绩数据

2e11643b6b849f30a0562991ee7d8aeb.png

察此数据集,可以发现,首先,三科考试的成绩是无法比较的。因为它们的均值和标准差相去甚远,所以对它们求平均值是没有意义的。你在组合这些考试成绩之前,必须将其变换为可比较的单元。其次,为了评定等级,你需要一种方法来确定某个学生在前述得分上百分比排名。再次,表示姓名的字段只有一个,为了正确地将其排序,需要将姓和名拆开。但以上每一个任务都可以巧妙地利用R中的数值和字符处理函数完成,接下来让我们开始本章的学习吧。

5-2  数学和统计函数

5.2.1  数学函数

表5-2 数学函数

0402549bafb215cf7208375b01bec8df.png

5.2.2 统计函数

表5-3 统计函数

8f47a413765ff3dcab039c54aa85a507.png

均值和标准差的计算:

#简洁的方式> x > mean(x)[1] 4. 5> sd(x)[1] 2. 449490#冗长的方法> n > meanx > css > sdx > meanx[1] 4. 5> sdx[1] 2. 449490

5.2.3 概率函数
在R中, 概率函数形如 :[dpqr] distribution_abbreviation()
其中第一个字母表示其所指分布的某一方面:
d = 密度函数( density)
p = 分布函数( distribution function)
q = 分位数函数( quantile function)
r = 生成随机数( 随机偏差)

表5-4 概率分布

比如正态分布的有关函数,如果不指定一个均值和一个标准差,则函数将假定其为标准正态分布(均值为0,标准差为1)。密度函数( dnorm)、分布函数( pnorm)、分位数函数( qnorm)和随机数生成函数( rnorm)的使用示例如下:

#在区间[–3, 3] 上绘制标准正态曲线, 如图5-1>x >y >plot(x, y,type = "l",xlab = "Normal Devi ate",ylab = "Densi ty",yaxs = "i ")#位于 z=1. 96 左侧的标准正态曲线下方面积是多少?>pnorm(1. 96)[1] 0. 97#均值为 500, 标准差为 100 的正态分布的 0. 9 分位点值为多少?>qnorm(. 9, mean=500, sd=100)[1] 628. 16#生成 50 个均值为 50, 标准差为 10 的正态随机数>rnorm(50, mean=50, sd=10)

c6240538f361611fa9ca6b52607445cc.png

图5-1

1. 设定随机数种子,生成服从正态分布的伪随机数

#生成服从正态分布的伪随机数, 函数set. seed() 让结果可以重现,函数runif() 用来生成0到1区间上服从均匀分布的伪随机> runif(5)[1] 0. 8725344 0. 3962501 0. 6826534 0. 3667821 0. 9255909> runif(5)[1] 0. 4273903 0. 2641101 0. 3550058 0. 3233044 0. 6584988> set. seed(1234)> runi f(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

2. 生成多元正态数据,mvrnorm( n, mean, sigma)
n是样本大小, mean为均值向量,而sigma是方差协方差矩阵(或相关矩阵)

比如,生成服从多元正态分布的数据:

#第一步, 设定随机数种子> li brary(MASS)> opti ons(di gi ts=3)> set. seed(1234)#第2步, 指定均值向量、 协方差阵> mean > si gma 6721. 2, 4700. 9, -16. 5,-47. 1, -16. 5, 0. 3) , nrow=3, ncol=3)#第3步, 生成数据、> mydata > mydata > names(mydata) 第4步, 查看结果> di m(mydata)[1] 500 3> head(mydata, n=10)y x1 x21 98. 8 41. 3 4. 352 244. 5 205. 2 3. 573 375. 7 186. 7 3. 694 -59. 2 11. 2 4. 235 313. 0 111. 0 2. 916 288. 8 185. 1 4. 187 134. 8 165. 0 3. 688 171. 7 97. 4 3. 819 167. 3 101. 0 4. 0110 121. 1 94. 5 3. 76

5.2.4 字符处理函数

数学和统计函数是用来处理数值型数据的,而字符处理函数是处理文本型数据的。

表5-5 字符处理函数

函 数

描 述

nchar( x)

计算x 中的字符数量x  length(x) 返回值为3 (参见表5-7)nchar(x[3]) 返回值为5

substr( x, start, stop)

提取或替换一个字符向量中的子串x  substr(x, 2, 4) 返回值为"bcd"
 substr(x, 2, 4) (x 将变成"a222ef"  )

grep( pattern, x, ignore.
 case=FALSE, fixed=FALSE)

x 中搜索某种模式。若fixed=FALSE,则pattern 为一个正则表达式。若fixed=TRUE,则pattern 为一个文本字符串。返回值为匹配的下标grep("A",c("b","A","c"),fixed=TRUE)  返回值为2

sub( pattern, replacement,x, ignore.case=FALSE,
 fixed=FALSE)

x 中搜索pattern,并以文本replacement 将其替换。若fixed=FALSE,则pattern 为一个正则表达式。若fixed=TRUE,则pattern  为一个文本字符串。sub("\\s",".","Hello There") 返回值为Hello.There。注意,"\s" 是一个用来查找空白的正则表达式;使用"\\s"  而不用"\" 的原因是,后者是R 中的转义字符(参见1.3.3 节)

strsplit( x, split,
 fixed=FALSE)

split 处分割字符向量x 中的元素。若fixed=FALSE,则pattern  为一个正则表达式。若fixed=TRUE,则pattern  为一个文本字符串y 将返回一个含有1 个成分、3 个元素的列表,包含的内容为"a"  "b" "c"
 unlist(y)[2] 和sapply(y,  "[", 2) 均会返回"b"

paste(…,  sep="")

连接字符串,分隔符为sep
 paste("x", 1:3,sep="") 返回值为c("x1", "x2", "x3")
 paste("x",1:3,sep="M") 返回值为c("xM1","xM2" "xM3")
 paste("Today is", date()) 返回值为Today is Thu Jun 25 14:17:32 2011

toupper( x)

大写转换toupper("abc") 返回值为"ABC"

tolower( x)

小写转换tolower("ABC") 返回值为"abc"

表5-6 其他实用函数#计算

515ac37580500c15eeb5b05fa039eb58.png

例如:其他使用函数, 举列子, 还有很多, 感兴趣可以去进一步阅读该书。

#求字符长度>x >length(x)[1] 3#提取字符>x >substr(x, 2, 4)[1] "bcd"

5.2.6 将函数应用于矩阵和数据框

1、将函数应用于数据对象:

#求标量5的开方> a > sqrt(a)[1] 2. 236068#将向量b舍入为指定位的小数> b > round(b)[1] 1 6 3#矩阵的c的log对数和均值> c > c[, 1] [, 2] [, 3] [, 4][1, ] 0. 4205 0. 355 0. 699 0. 323[2, ] 0. 0270 0. 601 0. 181 0. 926[3, ] 0. 6682 0. 319 0. 599 0. 215> log(c)[, 1] [, 2] [, 3] [, 4][1, ] -0. 866 -1. 036 -0. 358 -1. 130[2, ] -3. 614 -0. 508 -1. 711 -0. 077[3, ] -0. 403 -1. 144 -0. 513 -1. 538> mean(c)[1] 0. 444

2、将一个函数应用到矩阵的所有行( 列) , MARGIN=1 表示行, MARGIN=2 表示列。

#生成函数> mydata > mydata[, 1] [, 2] [, 3] [, 4] [, 5][1, ] 0. 71298 1. 368 -0. 8320 -1. 234 -0. 790[2, ] -0. 15096 -1. 149 -1. 0001 -0. 725 0. 506[3, ] -1. 77770 0. 519 -0. 6675 0. 721 -1. 350[4, ] -0. 00132 -0. 308 0. 9117 -1. 391 1. 558[5, ] -0. 00543 0. 378 -0. 0906 -1. 485 -0. 350[6, ] -0. 52178 -0. 539 -1. 7347 2. 050 1. 569#计算每行的均值> apply(mydata, 1, mean)> [1] -0. 155 -0. 504 -0. 511 0. 154 -0. 310 0. 165#计算每列的均值> apply(mydata, 2, mean)[1] -0. 2907 0. 0449 -0. 5688 -0. 3442 0. 1906#计算每行的截尾值> apply(mydata, 2, mean, tri m=0. 2)[1] -0. 1699 0. 0127 -0. 6475 -0. 6575 0. 2312

5-3  示例的一种解决方案

5.1 节中提出的问题是:将学生的各科考试成绩组合为单一的成绩衡量指标,基于相对名次(前20%、下20%、等等)给出从A到F的评分,根据学生姓氏和名字的首字母对花名册进行排序。下面给出了一种解决方案,一共8步。
步骤1  原始的学生花名册已经给出了。options(digits=2) 限定了输出小数点后数字的位数,并且让输出更容易阅读:

> options(digits=2)> roster Student Math Science English1 John Davis 502 95 252 Angela Williams 600 99 223 Bullwinkle Moose 412 80 184 David Jones 358 82 155 Janice Markhammer 495 75 206 Cheryl Cushing 512 85 287 Reuven Ytzrhak 410 80 158 Greg Knox 625 95 309 Joel England 573 89 2710 Mary Rayburn 522 86 18

步骤2 由于数学、科学和英语考试的分值不同(均值和标准差相去甚远),在组合之前需要先让它们变得可以比较。一种方法是将变量进行标准化,这样每科考试的成绩就都是用单位标准差来表示,而不是以原始的尺度来表示了。这个过程可以使用scale() 函数来实现:

> z > 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

步骤3 通过函数mean()来计算各行的均值以获得综合得分,并使用函数cbind() 将其添加到花名册中:

> score > roster > roster Student Math Science English score1 John Davis 502 95 25 0.5592 Angela Williams 600 99 22 0.9243 Bullwinkle Moose 412 80 18 -0.8574 David Jones 358 82 15 -1.1625 Janice Markhammer 495 75 20 -0.6296 Cheryl Cushing 512 85 28 0.3537 Reuven Ytzrhak 410 80 15 -1.0488 Greg Knox 625 95 30 1.3389 Joel England 573 89 27 0.69810 Mary Rayburn 522 86 18 -0.177

步骤4 函数quantile()给出了学生综合得分的百分位数。可以看到,成绩为A的分界点为0.74, B的分界点为0.44,等等。

> y > y 80% 60% 40% 20% 0.74 0.44 -0.36 -0.89

步骤5 通过使用逻辑运算符,你可以将学生的百分位数排名重编码为一个新的类别型成绩变量。下面在数据框roster中创建了变量grade。

> roster$grade[score >= y[1]] > roster$grade[score < y[1] & score >= y[2]] > roster$grade[score < y[2] & score >= y[3]] > roster$grade[score < y[3] & score >= y[4]] > roster$grade[score < y[4]] > roster Student Math Science English score grade1 John Davis 502 95 25 0.559 B2 Angela Williams 600 99 22 0.924 A3 Bullwinkle Moose 412 80 18 -0.857 D4 David Jones 358 82 15 -1.162 F5 Janice Markhammer 495 75 20 -0.629 D6 Cheryl Cushing 512 85 28 0.353 C7 Reuven Ytzrhak 410 80 15 -1.048 F8 Greg Knox 625 95 30 1.338 A9 Joel England 573 89 27 0.698 B10 Mary Rayburn 522 86 18 -0.177 C

步 骤 6  你 将 使 用 函 数 strsplit()以 空 格 为 界 把 学 生 姓 名 拆 分 为 姓 氏 和 名 字 。把strsplit() 应用到一个字符串组成的向量上会返回一个列表:

> name > 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"

步骤7 用函数sapply()提取列表中每个成分的第一个元素,放入一个储存名字的向量Firstname,并提取每个成分的第二个元素,放入一个储存姓氏的向量Lastname。"["是一个可以提取某个对象的一部分的函数——在这里它是用来提取列表name各成分中的第一个或第二个元素的。你将使用cbind() 把它们添加到花名册中。由于已经不再需要student变量,可以将其丢弃(在下标中使用–1 )。

> Firstname > Lastname > roster > roster  Firstname Lastname Math Science English score grade1 John       Davis  502    95    25     0.559   B2 Angela    Williams 600   99    22     0.924   A3 Bullwinkle   Moose   412   80   18   -0.857   D4 David       Jones   358    82   15  -1.162   F5 Janice    Markhammer 495   75   20   0.629   D6 Cheryl     Cushing  512    85   28  0.353    C7 Reuven    Ytzrhak   410    80    15  -1.048  F8 Greg     Knox      625   95    30   1.338   A9 Joel     England   573    89   27   0.698    B10 Mary    Rayburn   522    86   18  -0.177   C

步骤8 最后,可以使用函数order() 依姓氏和名字对数据集进行排序:

> roster[order(Lastname,Firstname),] Firstname Lastname Math Science English score grade6 Cheryl Cushing 512 85 28 0.35 C1 John Davis 502 95 25 0.56 B9 Joel England 573 89 27 0.70 B4 David Jones 358 82 15 -1.16 F8 Greg Knox 625 95 30 1.34 A5 Janice Markhammer 495 75 20 -0.63 D3 Bullwinkle Moose 412 80 18 -0.86 D10 Mary Rayburn 522 86 18 -0.18 C2 Angela Williams 600 99 22 0.92 A7 Reuven Ytzrhak 410 80 15 -1.05 F

5-4  控制流

控制流是为了可以重复复执行某些语句, 或者在满足特定条件的情况下执行另外的语句。

为了理解贯穿本节的语法示例,请牢记以下概念:

 语句( statement)是一条单独的R语句或一组复合语句(包含在花括号{ } 中的一组R
语句,使用分号分隔);
 条件( cond)是一条最终被解析为真( TRUE)或假( FALSE)的表达式;
 表达式( expr)是一条数值或字符串的求值语句;
 序列( seq)是一个数值或字符串序列。

5-4-1、重复和循环,f o r 结构和w h i l e结构

# for循环重复地执行一个语句, 直到某个变量的值不再包含在序列seq中为止, 如单词Hello被输出了10次。>for (i in 1: 10) print("Hello")# while循环重复地执行一个语句, 直到条件不为真为止, 如单词Hello被输出了10次。>i >while (i > 0) {print("Hello"); i 

; i 5-4-2、条件执行

1. i f - e l s e结构,制结构if-else在某个给定条件为真时执行语句。if (cond) statementif (cond) statement1 else statement2

if (is.character(grade)) grade if (!is.factor(grade)) grade 

2. ifelse结构ifelse结构是if-else结构比较紧凑的向量化版本,其语法为:ifelse( cond, statement1, statement2)

若cond为TRUE,则执行第一个语句;若cond为FALSE,则执行第二个语句。

ifelse(score > 0.5, print("Passed"), print("Failed"))outcome  0.5, "Passed", "Failed")

3. switch 结构switch根据一个表达式的值选择语句执行。语法为:switch( expr, ...)

> feelings > 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  整合(aggregate)与重构(reshape)

样本示例的数据主要来自R基本安装中的数据框mtcars。它描述了34种车型的设计和性能特点(汽缸数、排量、马力、每加仑汽油行驶的英里数,等等)。

5-5-1、数据集的转置(反转行和列),使用函数t()即可对一个矩阵或数据框进行转置。

#用R基础包的基础函数mtacars来反转行和列> cars > cars                 mpg  cyl  disp   hpMazda RX4        21.0  6   160   110Mazda RX4 Wag    21.0   6  160   110Datsun 710       22.8   4  108   93Hornet 4 Drive   21.4   6  258  110Hornet Sportabout 18.7  8 360   175> t(cars)   Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportaboutmpg       21           21         22.8          21.4         18.7cyl        6            6          4.0          6.0          8.0disp      160          160         108.0        258.0        360.0hp       110           110         93.0         110.0        175.0

5-5-2、整合数据

在R中使用一个或者多个by变量和一个预先定义好的函数来折叠(collapse)数据。aggregate(x, by, FUN)。x是数据对象,by是一个变量名组成的列表。而FUN则是用来计算描述性统计量的标量函数。

下面的例子将根据汽缸数和挡位数整合mtcars数据,并返回各个数值型变量的均值。

#设置数据为小数点后3位> options(digits=3)#加载mtcars数据>attach(mtcars)#按照cyl和gear> aggdata > aggdataGroup. 1 Group. 2 mpg cyl disp hp drat wt qsec vs am gear carb1      4       3 21.5 4  120  97 3.70 2.46 20.0 1.0 0.00 3 1.002      6       3 19.8 6  242  108 2.92 3.34 19.8 1.0 0.00 3 1.003      8       3 15.1 8  358  194 3.12 4.10 17.1 0.0 0.00 3 3.084      4       4 26.9 4  103  76  4.11 2.38 19.6 1.0 0.75 4 1.505      6       4 19.8 6  164  116 3.91 3.09 17.7 0.5 0.50 4 4.006      4       5 28.2 4  108  102 4.10 1.83 16.8 0.5 1.00 5 2.007      6       5 19.7 6  145  175 3.62 2.77 15.5 0.0 1.00 5 6.008      8       5 15.4 8  326  300 3.88 3.37 14.6 0.0 1.00 5 6.00

注意:在使用aggregate()函数的时候,by中的变量必须在一个列表中(即使只有一个变量),指定的函数可为任意的内建或自编函数。

5-5-3、reshape2 包是一套重构和整合数据集的万能工具

在使用reshape包时,首先将数据融合(melt),以使每一行都是唯一的标识符变量组合。然后将数据重铸( cast)为你想要的任何形状。在重铸过程中,你可以使用任何函数对数据进行整合。例子中使用的数据集如表5-7所示。

表5-7 原始数据

17c34c58baef85733ed7e7eec2dff0e8.png

1. 融合

 数据集的融合是指每个测量变量独占一行,行中带有要唯一确定这个测量所需的标识符变量。

#融合数据,melt()函数>install. packages("reshape2")#安装reshape包>library(reshape2)#加载reshape包>mydata   ID = c(1,1,2,2),  Time = c(1,2,1,2),  X1 = c(5,3,6,2),  X2 = c(6,5,1,4)) #按照表5-7创建数据匡并且赋予给mydata>md > melt(mydata, id = c("ID","Time"))  ID Time variable value1  1    1       X1     52  1    2       X1     33  2    1       X1     64  2    2       X1     25  1    1       X2     66  1    2       X2     57  2    1       X2     18  2    2       X2     4

2.重铸

dcast() 函数读取已融合的数据, 并使用你提供的公式和一个( 可选的) 用于整合数据的函数将其重塑。调用格式为:newdata

  • md为已融合的数据

  • formula : row1 + row2 ~ col1 + col2(row1 + row2 + ... 定义了要划掉的变量集合,以确定各行的内容,而col1 + col2 + ... 则定义了要划掉的、确定各列内容的变量集合)
  • fun.aggregate是(可选的)数据整合函数,当缺少FUN时,数据仅被重塑,而不被整合。

示例如下:

> dcast(md,ID ~ variable, mean)#执行整合  ID X1  X21  1  4 5.52  2  4 2.5> dcast(md, Time ~ variable, mean)#执行整合  Time  X1  X21    1 5.5 3.52    2 2.5 4.5> dcast(md, ID ~ Time, mean)#执行整合  ID   1 21  1 5.5 42  2 3.5 3> dcast(md, ID + Time ~ variable) # 不执行整合  ID Time X1 X21  1   1  5  62  1   2  3  53  2   1  6  14  2   2  2  4> dcast(md, ID + variable ~ Time)#不执行整合  ID variable 1 21  1       X1 5 32  1       X2 6 53  2       X1 6 24  2       X2 1 4> dcast(md, ID ~ variable+Time)#不执行整合ID X1_1 X1_2 X2_1 X2_2 1    5    3    6    5 2    6    2    1    4

30a6da25f09ee9c7a6b9bb04ff633d21.png

图5-2 使用函数melt() 和dcast() 重塑数据

小结:本章总结了数种用于处理数据的数学、统计和概率函数。我们学习了如何将这些函数应用到范围广泛的数据对象上,其中包括向量、矩阵和数据框。也学习了控制流结构的使用方法:用循环重复执行某些语句,或用分支在满足某些特定条件时执行另外的语句。最后,我们探索了折叠、整合以及重构数据的多种方法。在接下来的几章中,我们将学习多种将数据转化为信息的统计方法和图形方法。

后台回复“R语言实战”即可获取二维码加入R语言实战学习讨论群。

编辑:冯文清 李雪纯  校审:张健 罗鹏

478b80f9f44e400bf3b679380369641f.png

ffd6c80afe89faddbd15fa1c8e1f519d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值