在数据分析中,往往会遇到各种复杂的数据处理操作:分组、排序、过滤、转置、填充、移动、合并、分裂、去重、找重、填充等操作。这时候R语言就是一个很好的选择:R可以高效地、优雅地解决数据处理操作。(本章节为R语言入门第二部分总结篇:数据操作)
本章内容布局思路:思来想后,想到SQL查询的查询思路可以作为本章节的布局思路
- 1.了解表结构/数据结构
- 2.对表中的一些数据做出修改、替换、甚至生成新字段
- 3.from:数据合并/连接
- 4.where:条件筛选/过滤
- 5.group:分组
- 6.having和select:呈现不明显
- 7.order:排序
- 8.其他补充
目录 1. 初识R语言支持的数据类型
1.1 向量 Vector : c()
1.2 矩阵 Matrix: matrix()
1.3 数据框 DataFrame: data.frame()
1.4 时间序列 XTS: xts()
1.5 因子Factor:factor(补充)
2.查看数据概况
summary()和str()
3.修改/替换/重定义数据 4.数据合并
3.1 向量合并
3.2 cbind列合并(等长)
3.3 rbind行合并
3.4 merge
3.5 补充:集合操作
4.过滤/筛选
4.1 缺失值处理
4.2 数据增减
4.3 数值分段cut
5.分组操作
5.1 aggregate语法
5.2 aggregate分组计算
5.3 aggregate分组计算(formula形式)
6. 排序order 7. 计数table 8. 分裂split 9. 去重与找重unique 10.转置
1. 初识R语言支持的数据类型
开始之前,需要先了解一下R语言支持的数据类型,以及这些常用类型的特点。以下4种类型是最常用的:向量、矩阵、数据框、时间序列。
可参考↓↓ R语言|第2讲:生成数据 R语言快速入门:数据结构+生成数据+数据引用+读取外部数据
- 向量 Vector : c()
- 矩阵 Matrix: matrix()
- 数据框 DataFrame: data.frame()
- 时间序列 XTS: xts()
- 因子Factor:factor(补充)
(图片来自于粉丝日志) 1.1 向量 Vector : c()
> x > x [1] 1 2 3 4 5 6 7 8 9 10
1.2 矩阵 Matrix: matrix()
#矩阵用法matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,dimnames = NULL) #表示生成1行,1列的一个矩阵,其中仅仅包含一个元素“NA”#---示例---#> matrix(c(1,2,3, 11,12,13), nrow = 2, ncol = 3, byrow = TRUE, dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3"))) C.1 C.2 C.3row1 1 2 3row2 11 12 13#nrow = 2和ncol = 3 定义2x3的2行3列矩阵#byrow = TRUE 是控制矩阵中的数据c(1,2,3, 11,12,13)按照行的顺序排列,默认按照列排列#dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3")) 定义矩阵行名和列名
1.3 数据框 DataFrame: data.frame()
#其中" > x :15) > y :5) #将向量x和y合并存储到数据框中,并重命名为xf和yf> data.frame(xf = x, yf = y) xf yf1 11 12 12 23 13 34 14 45 15 5
1.4 时间序列 XTS: xts()
> library(xts)> x 11:> xts(x,order.by=as.Date('2019-09-14')+1:5) [,1]2019-09-15 112019-09-16 122019-09-17 132019-09-18 142019-09-19 15
关于xts类型的详细介绍,请参考文章《可扩展的时间序列xts》http://blog.fens.me/r-xts/
1.5 因子Factor:factor(补充)可以理解为分类变量
2.查看数据概况
在R中查看数据概况的函数常用summary()和str()。
其中,summary更多的是描述统计,返回:最大最小、四分位数、均值、中位数等;而str更多的是查看数据(变量)结构,返回:数据集维度数,列变量类型等。summary()和str()结合使用可以对数据概况作出初步了解。
> data(iris)> head(iris,10) Sepal.Length Sepal.Width Petal.Length Petal.Width Species1 5.1 3.5 1.4 0.2 setosa2 4.9 3.0 1.4 0.2 setosa3 4.7 3.2 1.3 0.2 setosa4 4.6 3.1 1.5 0.2 setosa5 5.0 3.6 1.4 0.2 setosa6 5.4 3.9 1.7 0.4 setosa7 4.6 3.4 1.4 0.3 setosa8 5.0 3.4 1.5 0.2 setosa9 4.4 2.9 1.4 0.2 setosa10 4.9 3.1 1.5 0.1 setosa> summary(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Species Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 setosa :50 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300 versicolor:50 Median :5.800 Median :3.000 Median :4.350 Median :1.300 virginica :50 Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800 Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500 > str(iris)'data.frame': 150 obs. of 5 variables: $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
3.修改/替换/重定义数据
修改指定单元格,修改指定列,within 关联修改
leadership$age[leadership$age==99] leadership$agecat2 leadership agecat2[age>75] "Elder" agecat2[age>=55 & age<=75] "Middle Aged" agecat2[age<55] )
4 数据合并
数据操作中,数据(集)合并是经常被用到。例如:合并来源不同,结构相似的两个表格 3.1 向量合并
#一维向量合并直接将要合并的变量以","分割放到c()中即可。> x > y > c(x,y) [1] 11 12 13 14 15 16 17 18 19 20 1 2 3 4 5 6 7 8 9 10
3.2 cbind列合并(等长)
总结:cbind等行数、按列合并(无序)
#生成测试数据> ID1 > ID2 > name> score> student1> student2#按照行合并student1和student2> cbind(student1,student2) ID1 name ID2 score1 1 A 2 82 2 B 3 223 3 C 4 74 4 D 5 6
3.3 rbind行合并
总结:按行合并,需要注意数据集需要有相同的列字段名
> #生成测试数据student1> ID :4)> score > student1 #生成测试数据student2> ID > score > student2#按行合并,需要注意数据集需要有相同的列字段名> rbind(student1,student2)ID score1 1 82 2 223 3 74 4 335 A 116 B 27 C 558 D 3
3.4 merge
#merge语法结构merge(x, y, by = intersect(names(x), names(y)), by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all, sort = TRUE, suffixes = c(".x",".y"), no.dups = TRUE, incomparables = NULL, ...)#其中,通过by字段控制连接字段by = "ID"为单字段连接,by = c("ID","NAME",……)为多字段连接;#通过all=FALSE/TRUE、all.x = TRUE和all.y = TRUE实现内连接、外连接、左连接和右连接
#———merge用法———#> #生成测试数据> ID1 > ID2 > name> score> student1> student2> > #内连接:保留交叉位置数据> merge(student1,student2,by.x = "ID1", by.y = "ID2",all=TRUE) ID1 name score1 1 A NA2 2 B 83 3 C 224 4 D 75 5 6> #左连接:保留左边所有数据及交叉y数据> merge(student1,student2,by.x = "ID1", by.y = "ID2",all.x=TRUE) ID1 name score1 1 A NA2 2 B 83 3 C 224 4 D 7> #右连接:保留右边所有数据及交叉x数据> merge(student1,student2,by.x = "ID1", by.y = "ID2",all.y=TRUE) ID1 name score1 2 B 82 3 C 223 4 D 74 5 6
3.5 补充:集合操作集合操作,是对2个向量的操作,处理2个向量之间的数值的关系,找到包含关系、取交集、并集、差集等。、
# 定义2个向量x,y> x3:[1] 3 4 5 6 7 8 NA> y6:[1] NA 6 7 8 9 10 NA# 判断x与y重复的元素的位置> is.element(x, y)[1] FALSE FALSE FALSE TRUE TRUE TRUE TRUE# 判断y与x重复的元素的位置> is.element(y, x)[1] TRUE TRUE TRUE TRUE FALSE FALSE TRUE# 取并集> union(x, y)[1] 3 4 5 6 7 8 NA 9 10# 取交集> intersect(x, y)[1] 6 7 8 NA# 取x有,y没有元素> setdiff(x, y)[1] 3 4 5# 取y有,x没有元素> setdiff(y, x)[1] 9 10# 判断2个向量是否相等> setequal(x, y)[1] FALSE
数据连接主要涉及到merge函数和dplyr包中的*_join等函数,
另外sqldf函数(SQL)亦可以实现数据连接功能。
参考→《R语言 数据(集)合并与连接/匹配 | 专题2》
4.过滤/筛选
过滤,是对数据集按照某种规则进行筛选,去掉不符合条件的数据,保留符合条件的数据。对于NA值的操作,主要都集中在了过滤操作和填充操作中,因此就不在单独介绍NA值的处理了。 可参考↓↓ R语言 | 第一部分:数据预处理 7.数据筛选和8.抽样 R语言数据管理与dplyr、tidyr | 第4讲 5 dplyr中5.1筛选filter和5.3选择select R 语言 逻辑运算:TRUE/FALSE | 专题3 4.1 缺失值处理
# 生成数据框> df+ b=c('B','A','B','B',NA),+ c=c(rnorm(2),NA,NA,NA));df a b c1 1 B -0.30418392 NA A 0.37001883 NA B NA4 2 B NA5 NA NA# 过滤有NA行的数据> na.omit(df) a b c1 1 B -0.3041839# 过滤,保留b列值为B的数据> df[which(df$b=='B'),] a b c1 1 B -0.30418393 NA B NA4 2 B NA
4.2 数据增减
常见如以下不同方法
#方法一:减行数或列数x=x[,-1] #代表删除x数据集中第一列数据#方法二:dplyr::mutate#数值重定义和赋值#将Ozone列取负数赋值给new,然后Temp列重新计算为(Temp - 32) / 1.8mutate(airquality, new = -Ozone, Temp = (Temp - 32) / 1.8)#方法三:subset筛选变量服从某值的子集subset(airquality, Temp > 80, select = c(Ozone, Temp))
4.3 数值分段数值分段,就是把一个连续型的数值型数据,按区间分割为因子类型的离散型数据。
> x [1] 1 2 3 4 5 6 7 8 9 10# 把向量转换为3段因子,分别列出每个值对应因子> cut(x, 3) [1] (0.991,4] (0.991,4] (0.991,4] (0.991,4] (4,7] (4,7] (4,7] (7,10] (7,10] (7,10]Levels: (0.991,4] (4,7] (7,10]# 对因子保留2位精度,并支持排序> cut(x, 3, dig.lab = 2, ordered = TRUE) [1] (0.99,4] (0.99,4] (0.99,4] (0.99,4] (4,7] (4,7] (4,7] (7,10] (7,10] (7,10]Levels: (0.99,4] < (4,7] < (7,10]
5 分组操作
此处仅讲述aggregate数据分组计算内容,更多分组计算内容
参考→《R语言 分组计算,不止group_by》
- dplyr包中的group_by联合summarize
- group_by和summarise单变量分组计算
- group_by和summarise多变量分组计算
- ddply分组计算示例
5.1 aggregate语法
aggregate(x, by, FUN)#x为数据集#by为分组变量列表#FUN为计算函数
5.2 aggregate分组计算
> row_names > col_names > df_matrix > df_matrix A B CA 1 10 19B 2 11 20C 3 12 21A 4 13 22B 5 14 23C 6 15 24A 7 16 25B 8 17 26C 9 18 27#注意分组变量为列表形式> aggregate(df_matrix,list(Group = row_names), mean) Group A B C1 A 4 13 222 B 5 14 233 C 6 15 24
5.3 aggregate分组计算补充(formula形式)
可以重点了解一下
aggregate(formula, data, FUN)#Formulas, one ~ one, one ~ many, many ~ one, and many ~ many:#一组对一计算变量函数型分组计算:计算变量~分组变量> aggregate(weight ~ feed, data = chickwts, mean) feed weight1 casein 323.58332 horsebean 160.20003 linseed 218.75004 meatmeal 276.90915 soybean 246.42866 sunflower 328.9167#多组对一函数型分组计算:计算变量~分组变量1+分组变量2……> aggregate(breaks ~ wool + tension, data = warpbreaks, mean) wool tension breaks1 A L 44.555562 B L 28.222223 A M 24.000004 B M 28.777785 A H 24.555566 B H 18.77778#一组对多计算变量,函数型分组计算:cbind(计算变量1,计算变量2)~分组变量1> aggregate(cbind(Ozone, Temp) ~ Month, data = airquality, mean) Month Ozone Temp1 5 23.61538 66.730772 6 29.44444 78.222223 7 59.11538 83.884624 8 59.96154 83.961545 9 31.44828 76.89655#多组对多计算变量,函数型分组计算:cbind(计算变量1,计算变量2)~分组变量1+分组变量2……> aggregate(cbind(ncases, ncontrols) ~ alcgp + tobgp, data = esoph, sum) alcgp tobgp ncases ncontrols1 0-39g/day 0-9g/day 9 2612 40-79 0-9g/day 34 1793 80-119 0-9g/day 19 614 120+ 0-9g/day 16 245 0-39g/day 10-19 10 846 40-79 10-19 17 857 80-119 10-19 19 498 120+ 10-19 12 189 0-39g/day 20-29 5 4210 40-79 20-29 15 6211 80-119 20-29 6 1612 120+ 20-29 7 1213 0-39g/day 30+ 5 2814 40-79 30+ 9 2915 80-119 30+ 7 1216 120+ 30+ 10 13
6. 排序
#order默认升序,变量前加“-”代表降序 #排序的操作,大多都是基于索引来完成的 #用order()函数来生成索引,再匹配的数据的数值上面。 可参考↓↓ R语言 排序&去重操作 | 专题1 R语言 | 第一部分:数据预处理
> row_names > col_names > set.seed(1234)> df_matrix A B C [1,] -1.207 -0.890 -0.837 [2,] 0.277 -0.477 2.416 [3,] 1.084 -0.998 0.134 [4,] -2.346 -0.776 -0.491 [5,] 0.429 0.064 -0.441 [6,] 0.506 0.959 0.460 [7,] -0.575 -0.110 -0.694 [8,] -0.547 -0.511 -1.448 [9,] -0.564 -0.911 0.575> df_frame group A B C1 A -1.207 -0.890 -0.8372 B 0.277 -0.477 2.4163 C 1.084 -0.998 0.1344 A -2.346 -0.776 -0.4915 B 0.429 0.064 -0.4416 C 0.506 0.959 0.4607 A -0.575 -0.110 -0.6948 B -0.547 -0.511 -1.4489 C -0.564 -0.911 0.575> > #order,其中默认升序,变量前加“-”代表降序> #排序的操作,大多都是基于索引来完成的> #用order()函数来生成索引,再匹配的数据的数值上面。> df_frame[order(df_frame$A),] group A B C4 A -2.346 -0.776 -0.4911 A -1.207 -0.890 -0.8377 A -0.575 -0.110 -0.6949 C -0.564 -0.911 0.5758 B -0.547 -0.511 -1.4482 B 0.277 -0.477 2.4165 B 0.429 0.064 -0.4416 C 0.506 0.959 0.4603 C 1.084 -0.998 0.134> df_frame[order(df_frame$group,-df_frame$A),] group A B C7 A -0.575 -0.110 -0.6941 A -1.207 -0.890 -0.8374 A -2.346 -0.776 -0.4915 B 0.429 0.064 -0.4412 B 0.277 -0.477 2.4168 B -0.547 -0.511 -1.4483 C 1.084 -0.998 0.1346 C 0.506 0.959 0.4609 C -0.564 -0.911 0.575
7. 计数
计数,是统计同一个值出现的次数。
# 生成20个随机数的向量set.seed(1234)xround(rnorm(# 统计每个值出现的次数table(x)hist(x,xlim = c(-10,13),breaks=5)
8 数据分裂
分裂计算,是把一个向量按照一列规则,拆分成多个向量的操作。有时候分裂split也被用于分组计算中。
> row_names > col_names > df_matrix > row_names > col_names > df_matrix A B C [1,] 1 10 19 [2,] 2 11 20 [3,] 3 12 21 [4,] 4 13 22 [5,] 5 14 23 [6,] 6 15 24 [7,] 7 16 25 [8,] 8 17 26 [9,] 9 18 27> df_frame group A B C1 A 1 10 192 B 2 11 203 C 3 12 214 A 4 13 225 B 5 14 236 C 6 15 247 A 7 16 258 B 8 17 269 C 9 18 27> df_split $A group A B C1 A 1 10 194 A 4 13 227 A 7 16 25$B group A B C2 B 2 11 205 B 5 14 238 B 8 17 26$C group A B C3 C 3 12 216 C 6 15 249 C 9 18 27
另外,可以用因子类型来控制分裂。分成2步操作,第一步先分成与数据集同样长度的因子,第二步进行分裂,可以把一个大的向量拆分成多个小的向量。
> # 生成因子规则> n > fat [1] 3 3 1 1 0 1 2 1 3 3 1 1 2 2 2Levels: 0 1 2 3> # 生成数据向量> x [1] -1.2107366 -1.3102467 -0.4083354 -0.5629753 1.2139442 1.6288760 -0.3160227 -1.8076242 -0.6125961[10] -2.1066644 1.2053009 1.3294407 -0.6836288 -1.7868047 0.1364916> # 对向量以因子的规则进行拆分> split(x, fat)$`0`[1] 1.213944$`1`[1] -0.4083354 -0.5629753 1.6288760 -1.8076242 1.2053009 1.3294407$`2`[1] -0.3160227 -0.6836288 -1.7868047 0.1364916$`3`[1] -1.2107366 -1.3102467 -0.6125961 -2.1066644
9. 去重与找重
去重,是把向量中重复的元素过滤掉。找重,是把向量中重复的元素找出来。可参考↓↓R语言 | 第一部分:数据预处理R语言 排序&去重操作 | 专题1R 语言 逻辑运算:TRUE/FALSE | 专题3
> x3:[1] 3 4 5 6 5 6 7 8# 去掉重复元素> unique(x)[1] 3 4 5 6 7 8# 找到重复元素,索引位置> duplicated(x)[1] FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE# 找到重复元素> x[duplicated(x)][1] 5 6
10.转置
转置是一个数学名词,把行和列进行互换,一般用于对矩阵的操作。
# 创建一个3行5列的矩阵> m1: [,1] [,2] [,3] [,4] [,5][1,] 1 4 7 10 13[2,] 2 5 8 11 14[3,] 3 6 9 12 15# 转置后,变成5行3列的矩阵> t(m) [,1] [,2] [,3][1,] 1 2 3[2,] 4 5 6[3,] 7 8 9[4,] 10 11 12[5,] 13 14 15