R语言实战Chapter4 基本数据管理

  • 操纵日期和缺失值
  • 熟悉数据类型的转换
  • 变量的创建和重编码
  • 数据集的排序、合并与取子集
  • 选入和丢弃变量

4.1创建leadership数据框

manager<-c(1,2,3,4,5)
date<-c("10/24/14","10/28/14","10/01/14","10/12/14","05/01/14")
country<-c("US","US","UK","UK","UK")
sex<-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,date,country,sex,age,q1,q2,q3,q4,q5,stringsAsFactors = FALSE)
leadership

R语言的正交实验设计 r语言实验四_数据


以下是我们本章节中基于这个数据框感兴趣的问题:

R语言的正交实验设计 r语言实验四_缺失值_02


R语言的正交实验设计 r语言实验四_数据_03

4.2创建新变量

变量名<-表达式

表达式可以包含多种运算符和函数:

R语言的正交实验设计 r语言实验四_缺失值_04

把两个变量加和为第三个变量,并创建一个新的变量存储这两个变量的均值,且把这两个新变量整合到原始的数据框中:

mydata<-data.frame(x1=c(2,2,6,4),x2=c(3,4,2,8))

#第一种方式
mydata$sumx<-mydata$x1+mydata$x2
mydata$meanx<-(mydata$x1+mydata$x2)/2

#第二种方式
attach(mydata)
mydata$sumx<-x1+x2
mydata$meanx<-(x1+x2)/2

#第三种方式
mydata<-transform(mydata,
                  sumx=x1+x2,
                  meanx=(x1+x2)/2)
mydata

R语言的正交实验设计 r语言实验四_数据_05


第三种方式(即用transform())更好,这种方式简化了按需创建新变量并将其保存到数据框中的过程

4.3变量的重编码

  • 将一个连续性变量修改为一组类别值
  • 将误编码的值替换为正确值
  • 基于一组分数线创建一个表示及格/不及格的变量

重编码数据可以使用一个或者多个逻辑运算符,返回值为TRUE或者FALSE

R语言的正交实验设计 r语言实验四_缺失值_06

比如我们将leadership数据集中经理人的连续型变量age重编码为类别型变量agecat(Young,Middle Aged,Elder):

#指定好年龄中的缺失值,即99岁
leadership$agecat[leadership$age==99]<-NA
#这句代码,[]中的condition返回值为TRUE的时候才执行这个赋值
#创建agecat变量
leadership$agecat[leadership$age>75]<-"Elder"
leadership$agecat[leadership$age>=55&
                    leadership$age<=75]<-"Middle Aged"
leadership$agecat[leadership$age<55]<-"Young"
#以下代码更加紧凑:
leadership$agecat[leadership$age==99]<-NA
leadership<-within(leadership,{
  agecat<-NA
  agecat[age>75]<-"Elder"
  agecat[age<=75&age>=55]<-"Middle Age"
  agecat[age<55]<-"Young"
})
leadership

within()与函数with()类似,不同的是它允许你修改数据框
car包里的recode()函数可以十分简便地重编码数值型、字符型向量或因子
doBy包里的recodevar()
R中自带的cut()可将一个数值型变量按照值域切割为多个区间,并返回一个因子

4.4变量的重命名
fix(leadership)可以调用一个交互式的编辑器,可以直接进行修改(例如把manager修改为mangerID,把date修改为testDate)

亦可以通过names()函数来重命名变量:
names(leadership)[2]<-“testDate” 把date重命名为testDate

names(leadership)
names(leadership)[2]<-"testDate"
#类似地
names(leadership)[6:10]<-c("item1","item2","item3","item4","item5")
#上述把q1到q5重命名为item1到item5
leadership

R语言的正交实验设计 r语言实验四_缺失值_07


最后,plyr包中有rename()函数可用来修改变量名:

R语言的正交实验设计 r语言实验四_数据_08

library(plyr)
leadership<-rename(leadership,
                   c(manager="managerID",date="testDate"))

4.5缺失值
R中的缺失值以NA(Not Available,不可用)表示,R中字符型和数值型数据使用的缺失值符号是相同的
is.na()允许你检测缺失值是否存在,它将返回一个相同大小的对象,如果某个元素是缺失值,相应的位置将被改写为TRUE,不是缺失值的位置则是FALSE:

is.na(leadership[,6:10])

R语言的正交实验设计 r语言实验四_r语言_09


注意:

R语言的正交实验设计 r语言实验四_r语言_10

4.5.1重编码某些值为缺失值

leadership$age[leadership$age==99]<-NA

表示99表示缺失值

4.5.2在分析中排除缺失值
一旦一个向量有缺失值,那么包含它的算式表达式和函数的结果也都是缺失值
好在多数数值函数都拥有一个na.rm=TRUE的选项,可以再计算之前移除缺失值并使用剩余值进行计算:

x<-c(1,2,NA,3)
y<-sum(x,na.rm = true())
y

R语言的正交实验设计 r语言实验四_数据集_11


可以使用na.omit()移除所有含有缺失值的观测,na.omit()可以删除所有含有缺失数据的行:

leadership#这是含有缺失数据的数据框
newdata<-na.omit(leadership)#这是删除了所有缺失值所在行的数据框
newdata

R语言的正交实验设计 r语言实验四_数据集_12


行删除在有少数缺失值或者缺失值比较集中在一小部分观测上的时候,是比较好用的方法,但如果缺失值遍布于数据之中或者一小部分变量中包含大量的缺失数据,行删除会剔除相当比例的数据。4.6日期值

日期值通常以字符串的形式输入到R中,然后转化为数值形式存储的日期变量

as.Date()用于执行这个转化:

as.Date(x,“input_format”),x是字符型数据,input_format给出了用于读入日期的适当形式

R语言的正交实验设计 r语言实验四_数据集_13


日期值的默认输入格式是yyyy-mm-dd:语句mydates<-as.Date(c(“2007-06-22”,“2004-02-13”))把默认格式的字符型数据转换为了对应的日期

而strDates<-c(“01/05/1965”,“08/16/1975”)

dates<-as.Date(strDates,“%m/%d%Y”)则使用mm/dd/yyyy的格式读取数据

  • Sys.Date()可以返回当天的日期
  • date()则返回当前的日期和时间
  • 函数format(x,format=“output_format”)来输出指定格式的日期值,并且可以提取日期值中的某些部分
today<-Sys.Date()
format(today,format="%B %d %Y")
format(today,format="%A")

R语言的正交实验设计 r语言实验四_数据集_14


format()函数可以接受一个参数(本例中是一个日期)并且按照某种格式输出结果(本例中使用的日期符号组合)

R在内部存储日期是,是使用自1970年1月1日以来的天数标示的,更早的日期为负数,这意味着在日期值上能执行算术运算:

startdate<-as.Date("2004-02-13")
enddate<-as.Date("2011-01-22")
days<-enddate-startdate
days

R语言的正交实验设计 r语言实验四_缺失值_15


最后,可以用函数difftime()来计算时间间隔,并且以星期、天、时、分、秒来表示:

我是2000年7月31日出生,那么我多大呢?

today<-Sys.Date()
dob<-as.Date("2000-7-31")
difftime(today,dob,units = "days")

R语言的正交实验设计 r语言实验四_数据_16


我7940天了(doge)

4.6.1将日期转换为字符型变量
同样也可以将日期转换为字符型变量,利用函数as.character()即可:

strDates<-as.character(dates)

进行转换后,即可使用一系列字符处理函数处理数据(如取子集、替换、连接等)

4.7类型转换

R中提供了一系列用来判断某个对象的数据类型和将其转换为另一种数据类型的函数:例如,向一个数值型向量中添加一个字符串会将此向量中的所有元素转换为字符型

R语言的正交实验设计 r语言实验四_缺失值_17


名为is.datatype()这样的函数返回TRUE或FALSE,而as.datatype()这样的函数则将其参数转换为对应的类型:

a<-c(1,2,3)
a
is.numeric(a)
is.vector(a)
a<-as.character(a)
a
is.numeric(a)
is.vector(a)
is.character(a)

当和控制流(如if-then)结合使用时,is.datatype()这样的函数将成为一类强大的工具,即允许根据数据的具体类型以不同的方式处理数据。另外,某些R函数需要接收某个特定类型(字符型或数值型、矩阵或数据框)的数据,as.datatype()这类函数可以在分析之前先将数据转换为要求的格式

4.8数据排序
order()函数对一个数据框进行排序,默认下是升序,在排序变量的前边加一个减号就可以得到降序的排序结果:

newdata<-leadership[order(leadership$age),]#创建了一个新数据集,其中各行按照age升序排序
attach(leadership)
newdata<-leadership[order(sex,age),]#各行依照女性到男性、同样性别中按年龄升序排序
detach(leadership)
attach(leadership)
newdata<-leadership[order(sex,-age),]#各行依照女性到男性、同样性别中降序排序
detach(leadership)
newdata

R语言的正交实验设计 r语言实验四_r语言_18

4.9数据集的合并

如果数据分散在多个地方,那么需要在下一步之前将其合并

4.9.1向数据框添加列

横向合并两个数据框(数据集),利用merge()函数,多数情况下,两个数据框是通过一个或多个共有变量进行连接的:

total<-merge(dataframeA,dateframeB,by=“ID”)

将dataframeA和dateframeB按照ID进行了合并

total<-merge(dataframeA,dateframeB,by=c(“ID”,“Country”))

则将两个数据框按照ID和Country进行了合并

R语言的正交实验设计 r语言实验四_数据集_19


4.9.2向数据框添加行

要纵向合并两个数据框(数据集),请使用rbind()函数:

total<-rbind(dataframeA,dataframeB)

两个数据框必须拥有相同的变量,不过它们的顺序不必一定相同。如果A中拥有B中没有的变量,那么务必要:

  • 删除A中多余的变量
  • 在B中创建追加的变量并将其设置为NA(缺失)

纵向连接通常用于向数据框中添加观测

4.10数据集取子集
R中有强大的索引功能,可以用于访问对象中的元素。也可以利用这个特性对变量或观测进行选入和排除

4.10.1选入(保留)变量
从一个大数据集中选择有限数量的变量来创建一个新的数据集。
以下两句代码等价:

#代码1
newdata<-leadership[,c(6:10)]
#代码2
myvars<-c("item1","item2","item3","item4","item5")
newdata<-leadership[myvars]

4.10.2剔除(丢弃)变量

可以利用以下代码

#剔除变量item3和item4
myvars<-names(leadership) %in%c("item3","item4")
newdata<-leadership[!myvars]
newdata

这个代码可以按照以下来理解

R语言的正交实验设计 r语言实验四_R语言的正交实验设计_20

或者直接

newdata<-leadership[c(-8,-9)]

即删除第八和第九个变量。原理:在某一列的下标之前加一个减号(-)就会剔除那一列

亦或者

leadership$item3<-leadership$item4<-NULL

一定要注意这里定义的NULL是未定义,和缺失值NA不同,定义了NULLL以后,这个数据框中定义为NULL的这个变量就被剔除了

丢弃和保留变量是互逆的操作,选择哪一种是看哪一种方式的编码简单。如果有许多变量需要丢弃,那么保留剩下的是更简单的,反之亦然

4.10.3进入观测

newdata<-leadership[1:3,]#选择前三行(前三个观测值)
newdata<-leadership[leadership$sex=="M"&leadership$age>30,]#选择所有30岁以上的男性
attach(leadership)
newdata<-leadership[leadership$sex=="M"&age>30,]
detach(leadership)

解析一下第二行代码:

R语言的正交实验设计 r语言实验四_缺失值_21


4.10.4subset()函数

subset()函数大概是选择变量和观测最简单的方法了:

例一

newdata<-subset(leadership,age>=35|age<24,select = c(q1,q2,q3,q4))

选择所有age大于等于35或age小于24的行,保留了变量q1到q4

例二

newdata<-subset(leadership,sex="M"&age>25,select = sex:q4)

选择所有25岁以上的男性,并保留了sex到q4以及中间的所有列

from:to 冒号运算符表示了变量from到变量to包含的所有变量

4.10.5 随机抽样
例如,你可能希望选择两份随机样本,使用其中一份样本构建预测模型,使用另一份样本验证模型的有效性

sample()函数:可以从数据集中(有放回或者无放回地)抽取大小为n的一个随机样本

mysample<-leadership[sample(1:nrow(leadership),3,replace = FALSE)]

sample()函数第一个参数是一个由要从中抽样的元素组成的向量(在这里,这个向量是1到数据框中观测的数量),第二个参数是要抽取的元素的数量,第三个参数表示无放回抽样
sample()函数会返回随机抽样得到的元素,之后即可用于选择数据框中的行

end