R语言实战第5章:高级数据管理

本章内容

  • 数字和统计函数
  • 字符处理函数
  • 循环和条件执行
  • 自编函数
  • 数据整合与重塑

5.1 一个数据处理难题

题目详见R语言实战第一版第86页(需要的同学,公众号私信:R语言实战。小编会发连接)

5.2 数值和字符处理函数

  1. 数值函数(数学、统计、概率)
  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

小结

  1. 基于R,包含数百个数学、统计和概率函数,这些函数对于操作数据很有用。它们可以广泛应用于数据对象,包括向量、矩阵和数据框。
  2. 掌握重复和循环以及条件执行。
  3. 在进行进一步分析之前,通常需要对数据进行整合或重构
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容