第四章
本章内容:
- 操作日期和缺失值
- 熟悉数据类型的转换
- 变量的创建和重编码
- 数据集的排序、合并与取子集
- 选入和丢弃变量
4.1 一个示例
新建示例(示例具体含义大家可以看下R语言实战第2版p69):
经理人 | 日期 | 国籍 | 性别 | 年龄 | q1 | q2 | q3 | q4 | q5 |
---|---|---|---|---|---|---|---|---|---|
1 | 10/24/08 | US | M | 32 | 5 | 4 | 5 | 5 | 5 |
2 | 10/28/08 | US | F | 45 | 3 | 5 | 2 | 5 | 5 |
3 | 10/01/08 | UK | F | 25 | 3 | 5 | 5 | 5 | 2 |
4 | 10/12/08 | UK | M | 39 | 3 | 3 | 4 | ||
5 | 05/01/09 | UK | F | 99 | 2 | 2 | 1 | 2 | 1 |
使用代码创建一个名为leadership的数据框存储上述表格
manager <- c(1,2,3,4,5)
data <- c('10/24/08','10/28/08','10/01/08','10/12/08','05/01/09')
country <- c('US','US','UK','UK','UK')
gender <- c('M','F','F','M','F')
age <- c(32,45,25,39,99)
q1 <- c(5,3,3,3,2)
q2 <- c(4,5,5,3,2)
q3 <- c(5,2,5,4,1)
q4 <- c(5,5,5,NA,2)
q5 <- c(5,5,2,NA,1)
leadership <- data.frame(manager, data, country, gender, age,q1,q2,q3,q4,q5,
stringsAsFactors = FALSE)
4.2 创建新变量
公式:
变量名 <- 表达式
“表达式”可以包含多种运算符和函数。
给数据框mydata
添加两个变量,x1x2之和,x1x2的平均数
mydata <- data.frame(x1 = c(2,2,6,4),
x2 = c(3,4,2,8))
# 方法一
mydata$sum <- mydata$x1 + mydata$x2
mydata$mean <- (mydata$x1 + mydata$x2)/2
# 方法二
attach(mydata)
sum <- x1 + x2
mean <- (x1 + x2)/2
detach(mydata)
# 方法三
mydata <- transform(mydata, sum = x1 + x2,
mean = (x1+x2)/2)
推荐大家使用方法三,简单快捷
4.3 变量的重编码
重编码
涉及根据同一变量和或其他变量的现有值创建新值的过程。
不妨假设你希望将leadership数据集中经理人的连续型年龄变量age重编码为类别型变量agecat(Young、 Middle Aged、Elder)。首先,必须将99岁的年龄值重编码为缺失值(因为不可能有人99岁了还当经理,我们默认99是缺失值),使用的代码为:
leadership$age[leadership$age == 99] <- NA
然后用以下代码创建新变量agecat为age的类别型变量
leadership$agecut[leadership$age > 60] <- "Elder"
leadership$agecut[leadership$age >= 40 &
leadership$age <= 60] <- "Middle Aged"
leadership$agecut[leadership$age < 40 ] <- "Young"
当然这个代码看起来很臃肿,可以用函数within()它和with()
类似,不同的就是函数within()可以允许你修改数据。
leadership <- within(leadership,{
agecut <- NA
agecut[age>60] <- 'Elder'
agecut[age>=40 & age<=60] <- 'Middle Aged'
agecut[age<40] <- 'Young'
})
此时agecut只是字符型变量,我们需要转换成有序型因子:
leadership$agecut <- factor(leadership$agecut,
levels = c('Young','Middle Aged','Elder'),
ordered = TRUE)
4.4 变量的重命名
方法一:
names(leadership)[1] <- "ManageID"
names(leadership)[2] <- "testDate"
方法二:使用plyr包中的函数rename()
使用格式:
rename(dataframe,c(oldname = 'newname', oldname = 'newname', ...))
install.packages("plyr") #已经安装了plyr包的略过这一步
library(plyr)
leadership <- rename(leadership,
c(manager = "ManageID",
date = "testData"))
4.5 缺失值
is.na()
检测缺失值是否存在。
is.na(leadership[,6:10])
## q1 q2 q3 q4 q5
## [1,] FALSE FALSE FALSE FALSE FALSE
## [2,] FALSE FALSE FALSE FALSE FALSE
## [3,] FALSE FALSE FALSE FALSE FALSE
## [4,] FALSE FALSE FALSE TRUE TRUE
## [5,] FALSE FALSE FALSE FALSE FALSE
检测数据框leadership
第6-10列是否有缺失值
注意:
- 缺失值被认为是不可比较的。
- R并不会把无限的或者不可能出现的标记为缺失值。正无穷和负无穷分别为
Inf和-Inf
,不可能的值用NaN表示。识别分别用is.infinite()或is.nan()
4.5.1 重编码某些值为缺失值
leadership$age[leadership$age == 99] <- NA
4.5.2 在分析中排除缺失值
很多函数自带参数na.rm = TRUE
,可以在计算之前移除缺失值使用剩余值计算
x = c(1,2,NA,4)
sum(x, na.rm = TRUE)
使用函数处理不完整的数据时,查下帮助文档,看看这些函数时如何处理缺失数据的。
na.omit()
移除所有含缺失值的观测。
(newdata = na.omit(leadership))
## ManageID testData country gender age q1 q2 q3 q4 q5 agecut
## 1 1 2008-10-24 US M 32 5 4 5 5 5 Young
## 2 2 2008-10-28 US F 45 3 5 2 5 5 Middle Aged
## 3 3 2008-10-01 UK F 25 3 5 5 5 2 Young
4.6 日期值
日期值通常以字符串的形式输入到R中,然后转化为以数值形式存储的日期变量。语法as.Data(x, "input_format")
日期格式如下表
符号 | 含义 | 示例 |
---|---|---|
%d | 数字表示的日期(0~31) | 01~31 |
%a | 缩写的星期名 | Mon |
%A | 非缩写星期名 | Monday |
%m | 月份(00~12) | 00~12 |
%b | 缩写的月份 | Jan |
%B | 非缩写月份 | January |
%y | 两位数的年份 | 07 |
%Y | 四位数的年份 | 2007 |
日期值默认输入格式为‘yyyy-mm-dd’
Sys.Date() #返回当前日期
## "2021-05-25"
Sys.time() #返回当前日期+时间
## "2021-05-25 16:44:31 CST"
使用format(x, format = "output_format")
来输出指定格式的日期值或提取日期值的某些部分
today = Sys.Date()
format(today, format = "%d/%m/%y")
## "25/05/21"
format(today, format = "%A")
## "星期二"
既然存储为了数值型数据,那日期是可以进行算术运算的
today = Sys.Date()
my_birth <- as.Date("1996-01-11")
days <- today - my_birth
days
## Time difference of 9266 days
函数difftime()
可以来计算时间间隔,并以星期、天、时、分、秒来表示(取决于参数units =
)。
difftime(today, my_birth, units = "weeks")
## Time difference of 1323.714 weeks
思考下大家可以知道my_birth这一天是周几吗?
format(my_birth, "%A")
## "星期四"
4.6.1 将日期转换为字符型变量
strdata = as.character(data)
# 举例
as.character(my_birth)
## "1996-01-11"
4.7 类型转换
类型转换函数
判断 | 转换 |
---|---|
is.numeric() | as.numeric() |
is.character() | as.character() |
is.vector() | as.vector() |
is.matrix() | as.matrix() |
is.data.frame() | as.data.frame() |
is.factor() | as.factor() |
is.logical() | as.logical() |
4.8 数据排序
order()
默认升序,在排序变量的前边加一个减号即可得到降序的排序结果。
举例:各行依女性到男性、同样性别中按年龄升序排序。
newdata <- leadership[order(leadership$gender,leadership$age),]
各行依女性到男性、同样性别中按年龄降序排序。
newdata <- leadership[order(leadership$gender, -leadership$age),]
4.9 数据集的合并
方法一:
横向合并两个数据框
total = merge(dataframeA, dataframeB, by = "ID")
将dataframeA和dataframeB按ID进行合并。
total = merge(dataframeA, dataframeB, by = c("ID","Country"))
将dataframeA和dataframeB按ID和Country进行合并。
方法二:
cbind()
横向合并,保证其正常工作需:每个对象必须拥有相同的行数、以同顺序排序。
方法三:
rbind()
total = rbind(dataframeA, dataframeB)
4.10 数据集取子集
4.10.1 选入(保留)变量
myvars <- paste0("q",1:5)
newdata <- leadership[myvars]
newdata2 <- leadership[,myvars]
newdata=newdata2保留q1-q5列
4.10.2 剔除(丢弃)变量
方法一:
myvar <- names(leadership) %in% c("q1","q2")
newdata <- leadership[!myvar]
newdata
方法二:只要要删哪一行,直接给出来即可
newdata <- leadership[c(-6,-7)]
方法三:知道要删哪个变量,直接赋值NULL
leadership$q1 = leadership$q2 = NULL
4.10.3 选入观测
举例:选出30岁以上的男性
select1 <- leadership[leadership$gender == 'M' & leadership$age > 30,]
研究范围限定在在2009年1月1日到2009年12月31日之间收集的观测上
min <- as.Date("2009-01-01")
max <- as.Date("2009-12-31")
select2 <- leadership[leadership$data > min & leadership$data < max,]
4.10.4 subset()函数
非常简单的选择变量和观测的方法
select3 <- subset(leadership, age>=35|age<24,
select = c(q1:q4))
第一个参数:要进行筛选的数据集
第二个参数:逻辑表达式—表示要留下的行(此处为留下年龄在24-35的人)
第三个参数:要留下的列(此处为留下q1-q4列)
4.10.5 随机抽样
select4 <- leadership[sample(1:nrow(leadership), 3, replace = FALSE),]
在数据挖掘和机械学习中常用。如你可能希望选择两份随机样本,一份用于构建预测模型,另一份用于验证模型的有效性。
小结
1、掌握创建新变量的函数transform(mydata, name1 = value1, name2 = value2, ...)
。
2、掌握within()
与with()
用法相似,不同点在于可以对变量进行修改。
3、掌握rename(dataframe,c(oldname = 'newname', oldname = 'newname', ...))
。对变量重命名。
4、掌握函数merge()和subset()