对数据集的处理远不止上一篇提到的子集,重编码等操作,有些时候数据集本身是有缺陷的,有些时候我们不能直接由数据集得到我们想要的东西。这一篇中我们使用下面的字符和数值型的数据集。
我们希望对这些学生的成绩进行一个综合评定,并评出A,B,C这样的等级。在姓名上,我们希望按照字母排序。但是一方面,姓名的字段只有一个,需要拆分;更麻烦的是,三门科目的成绩显然不能直接比较,方差平均值都是没有意义的。所以我们需要另辟蹊径。在接下来的内容中,我们先介绍R中自带的数值、字符型处理函数,然后用这些函数对这个数据集进行处理。
下表给出了常用的数学函数与统计函数,它们都是可以直接使用在向量和数据框上的。
abs(x); sqrt(x); ceiling(x); floor(x); trunc(x); #绝对值、平方根、向上取整、向下取整、向0取整,比如trunc(0.9)=trunc(-0.9)=0 round(x,n); signif(x,n); #round(3.473,2)=3.47, signif(3.473,2)=3.5,不同的四舍五入规则。 sin(x); cos(x); tan(x); #等等的一系列三角函数 log(x,n); #以n为底的对数函数,默认n=e,此外有log10()是自然对数。 mean(x); median(x); sd(x); var(x); #平均数、中位数、标准差、方差 range(x); sum(x); min(x); max(x); #值域、求和、最小值、最大值 diff(x,n) #n阶滞后差分,默认n-=1。比如diff(x=c(1,4,9,16))=c(3,5,7) scale(x,center=T,scale=T) #标准化,当两个参数都为T的时候会将列变成均值为0标准差为1的标准化数据;只有center=T时则会按列中心化。概率函数比较繁琐,它的总体形式为:[dpqr]distribution(); 其中:
d=求密度函数 (density)p=求分布函数 (distribution function)q=求分位数 (quantile function)r=随机生成概率函数 (random,随机误差) 常用的概率函数如下表:以标准正态分布为例,我们分别解决以下4个问题: 1)在[-3,3]区间上绘制分布曲线 2)求z=1.96左侧的曲线积分面积 3)均值为100,标准差为25的正态分布的0.9分位数是多少 4)生成25个均值为25,标准差为10的正态随机数 则代码分别为
x <- pretty(c(-3,3),100) #在-3到3中等距取100个点 y <- dnorm(x) #通过密度函数产生y plot(x,y,type="l") pnorm(1.96) qnorm(0.9,mean=100,sd=25) rnorm(25,mean=25,sd=10)注意到在生成随机数的时候,我们会用到随机种子,随机种子的函数是set.seed()
字符处理函数可以从字符串中抽取信息。
nchar(x) #计算字符串x中的字符个数 substr(x,start,stop) #求字符串子串;比如x="abcde",则substr(x,2,4)="bcd";substr(x,2,4) <- "dcb"则会令x变为"adcbe" sub(p,r,x) #在字符串x中**搜索**字段p并用字段r代替 strsplit(x,split) #在spilt处将x分割成两个字符串,输出是一个列表。 paste(x,y...,sep="") #将x,y...连接起来,连接符是sep,该例中为无缝连接。 toupper(x); tolower(x); #大写转换、小写转换最后依然要提及:大部分的函数都是可以运用在数据框和向量中的。
我们现在来解决开始提到的实际问题。假设数据集已经在某个csv中,并且我们已经将其读入了data变量中,现在只需要对其进行一定的处理以达到理想效果。处理代码如下:
> data 姓名 性别 数学 科学 英语 1 John Davis M 502 95 25 2 Angela Williams M 500 99 22 3 Bullinkle Moose F 412 80 18 4 David Jones M 358 82 15 5 Janice Markhammer F 495 75 20 6 Cheryl Cushing F 512 85 28 7 Reuven Ytzrhak F 410 80 15 8 Greg Knox M 625 95 30 9 Joel England F 573 89 27 10 Mary Rayburn F 522 86 18 z <- scale(data[,3:5]) #标准化后两列 score <- apply(z,1,mean) #求平均数,apply函数可以将函数运用到数组的某个维度上 data <- cbind(data,score) #列合并 y <- quantile(score,c(0.8,0.6,0.4,0.2)) #求分位数并标注成绩 data$grade[score>=y[1]] <- "A" data$grade[score<y[1] & score>=y[2]] <- "B" data$grade[score<y[2] & score>=y[3]] <- "C" data$grade[score<y[3] & score>=y[4]] <- "D" data$grade[score<y[4]] <- "F" data$姓名 <- as.character(data$姓名) #先将姓名转化成字符串型,再用strsplit分割 name <- strsplit((data$姓名)," ") lname <- sapply(name,"[",2) #sapply是apply的升级版,可以将函数运用在列表上(我们提到过strsplit()输出的是列表形式) fname <- sapply(name,"[",1) data <- cbind(fname,lname,data[,-1]) #列合并、排序、输出 data <- data[order(lname,fname),] > data fname lname 性别 数学 科学 英语 score grade 6 Cheryl Cushing F 512 85 28 0.3991003 C 1 John Davis M 502 95 25 0.6015507 B 9 Joel England F 573 89 27 0.7650623 A 4 David Jones M 358 82 15 -1.1701569 F 8 Greg Knox M 625 95 30 1.4233403 A 5 Janice Markhammer F 495 75 20 -0.5890825 D 3 Bullinkle Moose F 412 80 18 -0.8457295 D 10 Mary Rayburn F 522 86 18 -0.1274604 C 2 Angela Williams M 500 99 22 0.5808886 B 7 Reuven Ytzrhak F 410 80 15 -1.0375130 F本次笔记的内容只是中级数据操作中的基础部分,还有数据的整合和重铸,以及利用控制流来进行自编函数的内容会在下一次笔记中出现。这些内容单独抽成一次笔记显得单薄,但是却又是十分重要的。