本期回顾
R语言 | 第一部分:数据预处理
R语言|第2讲:生成数据
R语言常用的数据输入与输出方法 | 第三讲
本期目录
0 二维数组行列引用
1 创建新变量
2 变量重新编码
3 变量重新命名
4 缺失值
5 dplyr包的下述五个函数用法
5.1 筛选: filter
5.2 排列: arrange
5.3 选择: select
5.4 变形: mutate
5.5 汇总: summarise
5.6 分组: group_by
6 tidyr包的下述四个函数用法
6.1 宽数据转为长数据:gather (excel透视表反向操作)
6.2 长数据转为宽数据:spread (excel透视表功能)
6.3 多列合并为一列:unit
6.4 将一列分离为多列:separat
正 文
先前已经讲过R语言生成测试数据、数据预处理和外部数据输入等内容,但这仅仅是第一步,我们还需要对数据集进行筛选、缺失值处理等操作,以便获得可以应用于建模或者可视化的数据集(变量)。接下来就以鸢尾花测试数据集进行进一步的数据管理和筛选操作。
0 二维数组行列引用
代码语言:javascript复制> data(iris)
> head(iris,5) #显示前5行
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1 5.1 3.5 1.4 0.2 setosa
#2 4.9 3.0 1.4 0.2 setosa
#3 4.7 3.2 1.3 0.2 setosa
#4 4.6 3.1 1.5 0.2 setosa
#5 5.0 3.6 1.4 0.2 setosa
数据集管理中,首先必须懂“对指定维度数据的引用”。
例如:引用第一行数据,引用第一列数据,引用第一行第一列的数据。
代码语言:javascript复制> data(iris) #鸢尾花数据集
> dim(iris) #读取iris数据集的维度数值,以“行数 列数 ”形式展示
[1] 150 5
#说明iris数据集是150 x 5的二维数组
通过行列值引用:数据集[行值,列值]
如行值或列值仅1个数字,表示仅引用该行或列的数据
代码语言:javascript复制> iris[1,] #引用第1行数据
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
> head(iris[,1],5) #引用第1列的数据,其中因数据过长,使用head()函数取前5个数字
[1] 5.1 4.9 4.7 4.6 5.0
如行值或列值为组合数据,则表示引用组合行列交叉位置的数据
代码语言:javascript复制> iris[1:5,1:3]
Sepal.Length Sepal.Width Petal.Length
1 5.1 3.5 1.4
2 4.9 3.0 1.4
3 4.7 3.2 1.3
4 4.6 3.1 1.5
5 5.0 3.6 1.4
通过变量名引用(多用于二维数组中):数据集$变量名
代码语言:javascript复制> head(iris$Petal.Length,5)
[1] 1.4 1.4 1.3 1.5 1.4
1 创建新变量
在R语言中,可以通过变量计算/分布函数等生成数据,并赋值给特定变量。
代码语言:javascript复制> x <- (iris$Sepal.Length iris$Sepal.Width)/3
> x
[1] 2.866667 2.633333 2.633333 2.566667 2.866667 3.100000 2.666667 2.800000
[9] 2.433333 2.666667 3.033333 2.733333 2.600000 2.433333 3.266667 3.366667
[17] 3.100000 2.866667 3.166667 2.966667 2.933333 2.933333 2.733333 2.800000
[25] 2.733333 2.666667 2.800000 2.900000 2.866667 2.633333 2.633333 2.933333
[33] 3.100000 3.233333 2.666667 2.733333 3.000000 2.833333 2.466667 2.833333
[41] 2.833333 2.266667 2.533333 2.833333 2.966667 2.600000 2.966667 2.600000
[49] 3.000000 2.766667 3.400000 3.200000 3.333333 2.600000 3.100000 2.833333
[57] 3.200000 2.433333 3.166667 2.633333 2.333333 2.966667 2.733333 3.000000
[65] 2.833333 3.266667 2.866667 2.833333 2.800000 2.700000 3.033333 2.966667
[73] 2.933333 2.966667 3.100000 3.200000 3.200000 3.233333 2.966667 2.766667
[81] 2.633333 2.633333 2.833333 2.900000 2.800000 3.133333 3.266667 2.866667
[89] 2.866667 2.666667 2.700000 3.033333 2.800000 2.433333 2.766667 2.900000
[97] 2.866667 3.033333 2.533333 2.833333 3.200000 2.833333 3.366667 3.066667
[105] 3.166667 3.533333 2.466667 3.400000 3.066667 3.600000 3.233333 3.033333
[113] 3.266667 2.733333 2.866667 3.200000 3.166667 3.833333 3.433333 2.733333
[121] 3.366667 2.800000 3.500000 3.000000 3.333333 3.466667 3.000000 3.033333
[129] 3.066667 3.400000 3.400000 3.900000 3.066667 3.033333 2.900000 3.566667
[137] 3.233333 3.166667 3.000000 3.333333 3.266667 3.333333 2.833333 3.333333
[145] 3.333333 3.233333 2.933333 3.166667 3.200000 2.966667
算术运算符
- (加)
- -(减)
- *(乘)
- /(除)
- ^或 ** (求幂)
- x%%y (求余)
- x%/%y (商,整数)
2 变量重新编码
可用于将连续数据编码为分组数据,或者替代异常值等
在R中重新编码数据常用逻辑运算符,通过TRUE/FALSE等返回值,确定编码的位置。
代码语言:javascript复制> df <- iris
#将Petal.Length列等于1.4的位置重新编码为“”
> df$Petal.Length[df$Petal.Length == 1.4] <- ""
> head(df,10)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 0.2 setosa
2 4.9 3.0 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 0.3 setosa
8 5.0 3.4 1.5 0.2 setosa
9 4.4 2.9 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
同一变量分层编码
代码语言:javascript复制> df <- iris
> head(df,10) #编码前输出结果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 5.0 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
> df <- within(df,{
Petal.Length[Petal.Length == 1.4] <- "一点四"
Petal.Length[Petal.Length == 1.3] <- "一点三"
Petal.Length[Petal.Length == 1.5] <- "一点五"})
> head(df,10) #重新编码后输出结果
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 一点四 0.2 setosa
2 4.9 3.0 一点四 0.2 setosa
3 4.7 3.2 一点三 0.2 setosa
4 4.6 3.1 一点五 0.2 setosa
5 5.0 3.6 一点四 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 一点四 0.3 setosa
8 5.0 3.4 一点五 0.2 setosa
9 4.4 2.9 一点四 0.2 setosa
10 4.9 3.1 一点五 0.1 setosa
3 变量重新命名
通过names()函数重命名变量
代码语言:javascript复制> df <- iris
> head(df,5)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
> names(df)[5] <- "testNAME"
> head(df,5)
Sepal.Length Sepal.Width Petal.Length Petal.Width testNAME
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
4 缺失值
针对数据集中的缺失值,可以通过重新编码处理,还可以直接删除缺失值/缺失值行
删除缺失值行:na.omit()
代码语言:javascript复制> df <- matrix(c(1:5,NA,7:10),nrow=5)
> df
[,1] [,2]
[1,] 1 NA
[2,] 2 7
[3,] 3 8
[4,] 4 9
[5,] 5 10
> df <-na.omit(df)
> df
[,1] [,2]
[1,] 2 7
[2,] 3 8
[3,] 4 9
[4,] 5 10
attr(,"na.action")
[1] 1
attr(,"class")
[1] "omit"
5 dplyr包的下述五个函数用法【高级数据管理包】
代码语言:javascript复制# install.packages("dplyr")
library(dplyr)
#使用datasets包中的mtcars数据集做演示,首先将过长的数据整理成友好的tbl_df数据:
> mtcars_df = tbl_df(mtcars)
> head(mtcars_df)
# A tibble: 6 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
5.1 筛选: filter()
代码语言:javascript复制filter(mtcars_df,mpg==21,hp==110) #按给定的逻辑判断筛选出符合要求的子数据集
# A tibble: 2 x 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
5.2 排列: arrange()
代码语言:javascript复制arrange(mtcars_df, disp) #可对列名加 desc(disp)进行降序
5.3 选择: select()
代码语言:javascript复制> select(mtcars_df, disp:wt) #用列名作参数来选择子数据集:
# A tibble: 32 x 4
disp hp drat wt
<dbl> <dbl> <dbl> <dbl>
1 160 110 3.9 2.62
2 160 110 3.9 2.88
3 108 93 3.85 2.32
4 258 110 3.08 3.22
5 360 175 3.15 3.44
6 225 105 2.76 3.46
7 360 245 3.21 3.57
8 147. 62 3.69 3.19
9 141. 95 3.92 3.15
10 168. 123 3.92 3.44
# ... with 22 more rows
5.4 变形: mutate()
代码语言:javascript复制#取行
#取1:dim(mtcars_df)[1]行
mutate(mtcars_df, NO = 1:dim(mtcars_df)[1])
#数值重定义和赋值
#将Ozone列取负数赋值给new,然后Temp列重新计算为(Temp - 32) / 1.8
mutate(airquality, new = -Ozone, Temp = (Temp - 32) / 1.8)
5.5 汇总: summarise()
代码语言:javascript复制#对数据框调用其它函数进行汇总操作
summarise(mtcars_df,mdisp = mean(disp, na.rm = TRUE))
5.6 分组: group_by()
%>% 是管道函数,将左侧数据结果传递到右侧,作为右侧处理的原始数据
代码语言:javascript复制#当对数据集通过group_by()添加了分组信息后,mutate(),arrange() 和 summarise() 函数会自动对这些 tbl 类数据执行分组操作。
cars <- group_by(mtcars_df, cyl)
countcars <- summarise(cars, count = n()) # count = n()用来计算次数
# %>%管道函数,把相应的数据直接引用为右侧源数据集
countcars <- group_by(mtcars_df, cyl) %>% summarise(count = n())
6 tidyr包的下述四个函数用法
代码语言:javascript复制#install.packages("tidyr") #安装tidyr包
library(tidyr)
6.1 宽数据转为长数据:gather()
类似excel透视表反向操作
代码语言:javascript复制#gather(data, key, value, …, na.rm = FALSE, convert = FALSE)
#data:需要被转换的宽形表
#key:将原数据框中的所有列赋给一个新变量key
#value:将原数据框中的所有值赋给一个新变量value
#…:可以指定哪些列聚到同一列中
#na.rm:是否删除缺失值
widedata <- data.frame(person=c('Alex','Bob','Cathy'),grade=c(2,3,4),score=c(78,89,88))
#widedata
# person grade score
#1 Alex 2 78
#2 Bob 3 89
#3 Cathy 4 88
longdata <- gather(widedata, variable, value,-grade)
#longdata
# person variable value
#1 Alex grade 2
#2 Bob grade 3
#3 Cathy grade 4
#4 Alex score 78
#5 Bob score 89
#6 Cathy score 88
6.2 长数据转为宽数据:spread()
类似excel透视表操作
代码语言:javascript复制#spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)
#data:为需要转换的长形表
#key:需要将变量值拓展为字段的变量
#value:需要分散的值
#fill:对于缺失值,可将fill的值赋值给被转型后的缺失值
stocks <- data.frame(
time = as.Date('2009-01-01') 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
stocksm <- stocks %>% gather(stock, price, -time)
#stocksm
# time stock price
#1 2009-01-01 X -1.6411394
#2 2009-01-02 X -0.2144050
#3 2009-01-03 X -1.0630161
stocksm %>% spread(stock, price)
# time X Y Z
#1 2009-01-01 -1.6411394 -5.2254532 7.5666852
#2 2009-01-02 -0.2144050 0.3570096 4.8142193
#3 2009-01-03 -1.0630161 -1.3085735 7.3624203
stocksm %>% spread(time, price)
6.3 多列合并为一列:unit()
代码语言:javascript复制#unite(data, col, …, sep = “_”, remove = TRUE)
#data:为数据框
#col:被组合的新列名称
#…:指定哪些列需要被组合
#sep:组合列之间的连接符,默认为下划线
#remove:是否删除被组合的列
wideunite<-unite(widedata, col = information, person, grade, score, sep= "-")
wideunite
# information
#1 Alex-2-78
#2 Bob-3-89
#3 Cathy-4-88
6.4 将一列分离为多列:separate()
代码语言:javascript复制#separate()函数可将一列拆分为多列,一般可用于日志数据或日期时间型数据的拆分,语法如下:
#separate(data, col, into, sep = “[^[:alnum:]] ”, remove = TRUE,
#convert = FALSE, extra = “warn”, fill = “warn”, …)
#data:为数据框
#col:需要被拆分的列
#into:新建的列名,为字符串向量
#sep:被拆分列的分隔符
#remove:是否删除被分割的列
widesep <- separate(wideunite, information,c("person","grade","score"), sep = "-")
widesep
# person grade score
#1 Alex 2 78
#2 Bob 3 89
#3 Cathy 4 88
dplyr和tidyr参考鸿燕藏锋博客