在掌握数据的结构和导入之后(参见R的数据结构与导入),我们开始对数据进行操作处理,在本次笔记中我们使用一个5行10列的,主题是“领导行为的性别差异”的简单数据集,q1-q5是五项服从力评分,分数没有显著的优劣性。年龄=99代表缺失。整个数据集如下:
下文我们用le(leadship)的数据框变量来承载这个数据集。
创建新变量的格式是变量名 <- 表达式,除了四则运算以外,**^**表示求幂,x%%y表示求余(x mod y),x%/%y表示整数除法(x div y)。比如我们想要求出Q1+Q2的和,并把这一列并入原数据框中,那么有如下几种办法:
le$sum <- le$Q1+le$Q2
sumQ <- le$Q1+le$Q2
le <- cbind(le,sumQ) #按行合并
le <- transform(le,
sum = Q1+Q2) #这里只能用等于号
不同方法有不同特点,第一个最简单,但是容易写得冗长;第二个要注意行列合并的特点,第三个使用了transform(),注意内部只能使用=
利用逻辑运算可以对数据框中的变量进行重编码,下面给出一些逻辑运算:
< ; <= ; > ; >= ; == ; != #分别是小于、小于等于、大于、大于等于、严格相等(浮点型慎用)、不相等
!x ; x | y ; x & y ; isTRUE(x) #分别是非x,x或y,x与y,测试x是否为True
比如我们可以使用within函数对le增加一列年龄分布,定义30以下为Young,30-40为Mid,40以上为Old,当然我们不能忘记对缺失值的处理。
le$Age[le$Age==99] <- NA
le <- within(le,
{
agecat <- NA
agecat[Age>40] <- "Old"
agecat[Age<=40 & Age>30] <- "Mid"
agecat[Age<=30] <- "Young"
})
> le
ID Date National Sex Age Q1 Q2 Q3 Q4 Q5 sum sumQ agecat
1 1 10/24/14 US M 32 5 4 5 5 5 9 9 Mid
2 2 10/28/14 US F 45 3 5 2 5 5 8 8 Old
3 3 11/13/14 UK F 25 3 5 5 5 2 8 8 Young
4 4 08/30/14 UK M 39 3 3 4 NA NA 6 6 Mid
5 5 01/15/14 CH F NA 2 2 NA 2 1 4 4 <NA>
虽然可以用函数names()加方括号的形式,但是我们可以用fix()函数调出可交互的编辑器,然后直接重命名。
在数据框中,NA被识别为缺失值,它们是不可计算的,通过函数is.na()可以判断识别缺失值:
> is.na(le[8:10])
Q3 Q4 Q5
1 FALSE FALSE FALSE
2 FALSE FALSE FALSE
3 FALSE FALSE FALSE
4 FALSE TRUE TRUE
5 TRUE FALSE FALSE
我们可以看到le数据集的8-10列中有3个缺失值。
虽然缺失值不可计算比较,但我们可以类似Age中的例子将其重编码。在计算的时候也可以用na.rm参数来只能识别,移除缺失值。
> sum(le$Q3)
[1] NA
> sum(le$Q3,na.rm=T)
[1] 16
最后,我们可以使用na.omit()直接删除含缺失值的行。
> na.omit(le)
ID Date National Sex Age Q1 Q2 Q3 Q4 Q5 sum sumQ agecat
1 1 10/24/14 US M 32 5 4 5 5 5 9 9 Mid
2 2 10/28/14 US F 45 3 5 2 5 5 8 8 Old
3 3 11/13/14 UK F 25 3 5 5 5 2 8 8 Young
对缺失值的处理,在统计学上有专业的方法,我们日后再提。现在我们需要知道的是,缺失值是不可操作的,但是也不能轻易丢弃,否则会影响统计性质和分析结果。
日期值输入的时候一般是字符变量,而后可以转化成数值变量,函数为as.Date(),默认输入是yyyy-mm-dd,也可以设置为mm/dd/yyyy,此外,还有一些有趣的函数,见下面的例子。
md <- as.Date("2017-11-01")
> md
[1] "2017-11-01"
> class(md) #md的类型是Date
[1] "Date"
mf <- "%m/%d/%y"
le$Date <- as.Date(le$Date,mf) #将le数据集中的date变量转化成date类型
> class(le$Date)
[1] "Date"
> Sys.Date() #当前日期
[1] "2017-11-09"
> date() #系统时间
[1] "Thu Nov 09 22:37:14 2017"
> md-Sys.Date() #可以做减法
Time difference of -8 days
birth <- as.Date("1995-01-10")
> difftime(md,birth,units="weeks") #计算日期差
Time difference of 1190.143 weeks
最后,timeDate包对日期的处理和分析很有帮助,lubridate包则有很多简化日期的函数,可以安装后通过help()去挖掘。
用函数可以很简单地进行类型转换
as.numeric() #数值型
as.character() #字符型
as.vector() #向量型
as.matrix() #矩阵
as.data.frame() #数据框
as.factor() #因子
as.logical() #布尔型
将上述的as换成is会变成判断函数,判断一个变量是否为该类型,输出为T或F。
使用order函数可以简单地排序。
le <- le[order(le$Sex,-le$Age),]
> le
ID Date National Sex Age Q1 Q2 Q3 Q4 Q5
5 5 01/15/14 CH F 99 2 2 NA 2 1
2 2 10/28/14 US F 45 3 5 2 5 5
3 3 11/13/14 UK F 25 3 5 5 5 2
4 4 08/30/14 UK M 39 3 3 4 NA NA
1 1 10/24/14 US M 32 5 4 5 5 5
这里先按性别排序(女性→男性),然后再按年龄降序处理。
合并的问题,只需要用到列合并cbind()和行合并rbind()两个函数即可,如果只是普通的加行,可以考虑merge()函数,比如:
total <- merge(dataframeA,dataframeB,by"=ID")
可以将A,B两个数据框按照列进行联结,by参数可以是一个向量,这样进行的联结是多重的。
当数据集很大的时候,我们往往只需要取某些子集进行观测。选取的方法有很多种:
选入变量:当我们要选后面5个问题Q1-Q5的列的时候
ss <- c("Q1","Q2","Q3","Q4","Q5")
newdata <- le[ss]
newdata <- le[,c(6:10)]
这两种写法是等价的,前者只知道要选取变量的名称,后者是知道要选取的变量的列。
同理,当我们舍弃变量时,也有若干种写法
ss <- name(le) %in% c("Q3","Q4")
newdata <- le[!ss]
newdata <- le[c(-8,-9)]
newdata <- le
newdata$Q3 <- newdata$Q4 <- NULL
最后一种方法是将Q3,Q4列赋值为NULL未定义。
当数据集很大,取子集条件很多的时候,就要使用subset函数。subset()可以玩成上述的选取和舍弃的操作,还可以完成更多带条件的复杂的取子集操作。
newdata <- subset(le,Age >=35 | Age <24,select=c(Q1,Q2,Q3,Q4,Q5))
newdata <- subset(le,Sex="F" & Q1>2,select=National:Q2)
subset()的构成是:数据集、条件、列数,通过上面两个例子可以看出来。
我们还可能会对数据集进行随机取样操作,这里要用到sample函数:
ms <- le[sample(1:nrow(le),3,replace=F,]
语句意思为从le数据集中不放回地抽取3个数据。nrow(le)是le的行数,我们也可以只对le的前几行进行取样,但这是一种二次取样,可能会影响分析结果。
这些都只是初级的变量处理和数据框操作,下一份笔记会讲更为繁复的管理操作,包括R中函数的编写。