R语言由浅入深:二、数据处理
第二章、数据处理
一、变量的创建、编码、命名
将数据表示为矩阵或数据框仅是数据准备的第一步,数据分析时,大量的时间都花在了数据处理上
1.创建新变量 变量名<-表达式
2.算数运算符
运算符 |
描述 |
+ |
加 |
- |
减 |
* |
乘 |
/ |
除 |
^或** |
求幂 |
x%%y |
求余(x mod y) 5%%2=1 |
x%/%y |
整数除法。 5%/%2=2 |
3.创建新变量的例子
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
#我们可以看出,在对属性进行操作时都是按照一列一列对应操作的
4.变量重编码 Recoding Variables
重编码是指根据已有变量创建新变量的过程。
比如:将一个连续型变量变为一组类别值、将误编码的值替换为正确值、基于一组分数创建一个表示及格/不及格的变量
要重编码。可以使用R中的逻辑运算符,返回值为布尔类型
运算符 |
描述 |
< |
小于 |
<= |
小于或等于 |
> |
大于 |
>= |
大于或等于 |
== |
严格等于 |
!= |
不等于 |
! x |
非x |
x | y |
x或y |
x & y |
x和y |
isTRUE(X) |
测试x是否为TRUE |
5.例子:
(1)数据准备(调查问卷)
manager <- c(1, 2, 3, 4, 5)
date <- c("10/24/08", "10/28/08", "10/1/08", "10/12/08", "5/1/09")
country <- c("US", "US", "UK", "UK", "UK")
gender <- c("M", "F", "F", "M", "F")
age <- c(32, 45, 25, 39, 99) #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, gender, age,
q1, q2, q3, q4, q5, stringsAsFactors=FALSE)
(2)变量重编码
#根据年龄进行分类,重编码
#[leadership$age > 75] 得到的结果相当于 leadership[c(false,false,false,false,true)]
#选取了值为true的位置的值
leadership$agecat[leadership$age > 75] <- "Elder"
leadership$agecat[leadership$age >= 55 & leadership$age <= 75] <- "Middle Aged"
leadership$agecat[leadership$age < 55] <- "Young"
查看处理结果:
(3)用within()改写
leadership <- within(leadership,{
agecat <- NA #先进性初始化
agecat[age > 75] <- "Elder"
agecat[age >= 55 & age <= 75] <- "Middle Aged"
agecat[age < 55] <- "Young" })
如果不用<-赋值回给leadership,则在运行结果为临时值,原leadership不会被改变。
6.变量重命名:
(1)fix()可以调用一个交互式的编辑器,单机变量名,然后在弹出的对话框中将其重命名。
例如:fix(leadership)
注:edit和fix函数的区别
只用edit(X)在窗口中编辑修改X,关闭窗口后X没有改变,应使用Y<-edit(X);使用fix(X)在窗口只中编辑修改X,关闭窗口后X就是修改后的值,不必使用Y<-fix(X)。
(2)变量重命名方法一:rename()
reshape包中有一个rename()函数,可用于修改变量名。
install.packages("reshape") #先安装包
library(reshape)
leadership <- rename(leadership,
c(manager="managerID", date="testDate") )
(3)变量重命名方法二:names()
#查看所有变量名
names(leadership)
names(leadership)[2] <- "testDate"
#将q1到q5重命名为item1到item5
names(leadership)[6:10] <- c("item1",
"item2", "item3", "item4", "item5")
二、缺失值、日期值处理,数据类型转化,数据排序
1.缺失值
在R中,缺失值以符号NA(Not Available,不可用)表示。不可能出现的值通过符号NaN(Not a Number,非数值)来表示。
(1)检测缺失值是否存在 is.na()
(2)重编码某些值为缺失值
在之前的示例中,缺失的年龄值被编码为99,任何等于99的年龄值都应该被修改为NA。
leadership$age[leadership$age==99] <- NA
(3)在分析中排除缺失值
①由于含有缺失值的算术表达式和函数的计算结果也是缺失值:需要删除。
②多数的数值函数都有一个na.rm=TRUE选项,在计算过程中略掉NA值
③na.omit()可以删除所有含缺失数据的行:
newdata <- na.omit(leadership)
2.日期值
通常以字符串的形式输入到R中,然后转化为数值形式存储的日期变量。
函数as.Date()用于执行这种转化。其语法为as.Date(x,"input_format"),其中x是字符型数据,input_format则给出了用于读入日期的适当格式。
(1)日期格式:
符号 |
含义 |
示例 |
%d |
数字表示的日期(0~31) |
01~31 |
%a |
缩写的星期名 |
Mon |
%A |
非缩写星期名 |
Monday |
%m |
月份 |
00~12 |
%b |
缩写的月份 |
Jan |
%B |
非缩写的月份 |
January |
%y |
两位数的年份 |
07 |
%Y |
四位数的年份 |
2007 |
(2)日期值的默认输入格式为yyyy-mm-dd
mydates<-as.Date(c("2007-06-22","2004-02-13"))
在leadership数据集中,日期是以mm/dd/yy的格式编码为字符型变量的。需要转化:
leadership$date <- as.Date(leadership$date, "%m/%d/%y")
(3)返回当天的日期:Sys.Date()
返回当前的日期和时间:date()
输出指定格式的日期值:format(x,format="output_format")
例:
可以看出并没有改变today的值
(4)日期值的相关计算:
R的内部使用自1970年1月1日以来的天数 表示日期,更早的日期表示为负数。可以在日期值上执行算术运算:
startdate <- as.Date("2004-02-13")
enddate <- as.Date("2011-01-22")
days <- enddate - startdate #默认的是天数表示
计算周数:
difftime(enddate, startdate, units="weeks")
将日期转化为字符型变量(不常用)
strDates <- as.character(dates)
3.数据类型转换
R提供了一系列用于判断某个对象的数据类型和将其转换为另一种数据类型的函数。
判断 |
转换 |
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() |
判断的返回值为TRUE/FALSE
as.datatype()将参数转换为对应类型。
(1)数据类型转换示例:
a <- c(1,2,3)
is.numeric(a)
is.vector(a)
a <- as.character(a)
a
is.numeric(a)
is.vector(a)
is.character(a)
(2)数据类型转换的用处
①与控制流(如if-then)结合使用时,is.datatype()这样的函数将成为一类强大的工具,即允许根据数据的具体类型以不同 的方式处理数据。
②某些R函数需要接受某个特定类型(字符型或数值型,矩阵或数据框)的数据,as.datatype()这类函数可以在分析之前先行 将数据转换为要求的格式。
4.数据排序
三、数据集的合并,选取子集,使用SQL操作数据框,数据的整合与重构
1.数据集的合并(Merging)
如果数据分散在多个地方,就需要在进一步分析数据之前先将数据进行合并
(1)添加列(添加变量)
①要横向合并两个数据集,使用merge()函数。两个数据框是通过一个或多个共有变量进行联结的(inner join)。例如
total <- merge(dataframeA, dataframeB, by="ID")
将两个数据框按照ID进行合并
total <- merge(dataframeA, dataframeB, by=c("ID","Country"))
将两个数据框按照两个共有变量ID和Country进行了合并。
②直接横向合并,AB
直接横向合并两个矩阵或数据框,并且不需要指定一个公共索引,那么可以直接使用cbind()函数(colum bind):
total <- cbind(A, B)
这个函数将横向合并对象A和对象B。为了让它正常工作,每个对象必须拥有相同的行数,且要以相同顺序排序。
(2)添加行(添加观测)
要纵向合并两个数据框(数据集),使用rbind()函数(row bind)
total <- rbind(dataframeA, dataframeB)
两个数据框必须拥有相同的变量(相同的列),不过顺序不必相同。如果dataframeA中拥有 dataframeB中没有的变量,在合并之前做 以下某种处理:
①删除dataframeA中的多余变量;
②在dataframeB中创建追加的变量并将其值设为 NA(缺失)。
2.数据集选取子集
对变量和观测进行保留或删除的方法
(1)选入(保留)变量
从一个大数据集中选择有限数量的变量来 创建一个新的数据集。
数据框中的元素是通过dataframe[row indices, column indices]来访问的。可以沿用这种方法来选择变量。例如:
选出了6-10列数据
等价于:
myvars <- c("q1", "q2", "q3", "q4", "q5")
newdata <-leadership[myvars]
(2)剔除(丢弃)变量
如果某个变量中有若干缺失值,则需要在进一步分析之前将其丢弃
①方法一:
myvars <- names(leadership) %in% c("q3", "q4")
newdata<-leadership[!myvars]
选取变量时采用逻辑型向量注意:
leadership[c(TRUE, FALSE, FALSE),]
– 如果行数大于3:会得到1、4、7、10、13、 16……行
leadership[c(TRUE, FALSE),]
– 如果行数大于2:会得到1、3、5、7……行
②方法二:
因为知道q3和q4是第7个和第8个变量(使用-来表示要剔除的数据),也可以使用语句将其剔除:
newdata<-leadership[c(-7,-8)]
③方法三:
leadership$q3 <- leadership$q4 <- NULL
– 注意!:此种方法会直接作用于leadership。
– 此语句实为两句:
• leadership$q3 <- NULL
• leadership$q4 <- NULL
(3)选入观测
• 选择了第1行到第3行(前三个观测)
newdata <- leadership[1:3,]
• 选择了所有30岁以上的男性
newdata <- leadership[leadership$gender=="M" &leadership$age > 30,]
这里记录一下在查询的时候出现的问题:
没有加上“,”,致使运行的为leadership[c(1,4)],所以得到的是第1,4,6,9列这样一直循环取值
注意“,”一定不能忘掉leadership[c(1,4),]这才是第1,4行
更加清楚地认识到下面的解释:
(4)subset()函数——最简单的方法
subset函数是选择变量和观测最简单的方法
例,选择所有age值大于等于35或age值小于24的行,保留了变量q1到q4:
例,选择所有25岁以上的男性,并保留了变量gender到q4和其间所有列:
(5)随机抽样
在分析数据时,要创建两份随机样本,使用其中一份样本构建预测模型,使用另一份样本验证模型的有效性。
①simple()函数能够在数据中(有放回或无放回)抽取大小为n的一个随机样本。
②示例:
sample()函数中的第一个参数是一个由要从 中抽样的元素组成的向量。在这里,这个向量是1到数据框中观测的数量,第二个参数是要抽取的元素数量,第三个参数表示无放回抽样。
3.使用SQL语句操作数据框
安装sqldf包
install.packages("sqldf")
使用sqldf()函数在数据框上使用SQL中的 SELECT语句。
例:(mtcars数据包含于R的基本安装中)
library(sqldf)
newdf <- sqldf("select * from mtcars where carb=1 order by mpg")
4.数据的整合和重构
(1)转置:反转行和列,使用函数t()
例:
使用转置函数
(2)分类汇总
分类汇总的函数为aggregate(x,by,FUN)
x是待分类的数据对象;
by是一个变量名组成的列表,用于对原有观测进行分类
FUN是用来计算描述性统计量的函数,它将被用来计算新观测中的值。
这个代码意思是:按照变量cyl,gear来分类别,属于相同类的所有数据各个变量取均值(执行FUN函数);group.1和group.2表示了分类值。
注:by中变量必须在一个列表中,即使只有一个变量
(3)reshape包
reshape包是一套整合和重构数据集的万能工具,主要分为melt和cast过程
(4)reshape包的使用示例
①数据准备:
mydata <- read.table(header=TRUE, sep=" ",
text="
ID Time X1 X2
1 1 5 6
1 2 3 5
2 1 6 1
2 2 2 4")
②melt过程
将数据重构为这样的格式:每个变量独占一行,行中带有要唯一确定这个测量所需的标识符变量。
③cast过程(好好理解一下)
cast()函数读取已融合的数据,并使用你提 供的公式和一个(可选的)用于整合数据 的函数将其重塑。调用格式为:
newdata <- cast(md, formula, FUN)
其中的md为已融合的数据,formula描述了想要的最后结果,而FUN是(可选的)数据整合函数。
例子:
四、控制流:条件与循环
1.基本概念
语句statement、条件cond、表达式expr、序列seq
2.条件执行结构:
(1) if-else
语法结构:
—if(cond) statement
—if(cond) statement1 else statement2
(2) ifelse
此结构是if-else结构紧凑的向量化版本
语法结构:
—ifelse(cond,statement1,statement2)
(3) switch
语法结构:
switch(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"
)
)
输出结果
(4)for循环
语法结构:for(var in seq) statement
(5)while循环
语法结构
while (cond) statement
注意:在处理大数据集中的行和列时,R中的循环可能比较低效费时。只要可能,最好联用R中的内建数值/字符处理函数和 apply族函数。
五、用户自定义函数
语法:
例1:
mysum<-function(x,y){
z<-x+y
return(z)
}
mysum(1,5)
例2:可以为自定义函数设置默认值
#此函数输出当前日期,可让用户选择输出格式,在函数声 明中为参数指定的值将作为其默认值。
mydate <- 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\n"))
}