[R语言实战]Chapter 4 基本数据管理

Chapter4 基本数据管理

  1. 一个示例

    创建leadership数据库

    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)
    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,1)
    q5 <- c(5,5,2,NA,1)
    leadership <- data.frame(manager,date,country,gender,age,q1,q2,q3,q4,q5,stringsAsFactors = F)
    

    4.2 创建新变量

    在典型的研究项目中,你可能需要创建新变量或者对现有的变量进行变换。通过 变量名<- 表达式 来完成。

    算术运算符

+,-,*,/ 加减乘除
^ or ** 求幂
x%%y 求余(x mod y).5%%2的结果为1
x%/%y 整数除法。5%/2% 的结果为2

提取旧变量并创建新变量的三种方式

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
View(mydata)
##方式二
rm(mydata) #移除mydata之前赋值的信息
attach(mydata)
mydata$sumx <- x1+x2
mydata$meanx <- (x1+x2)/2
detach(mydata)
##方式三
rm(mydata)
mydata <- transform(mydata,
                    sumx=x1+x2,
                    meanx=(x1+x2)/2)

作者认为更倾向于第三种方式,即transform()函数,简化了按需创建新变量并将其保存到数据框中的过程。

4.3 变量的重编码

重编码涉及根据同一个变量或其他变量的现有值创建新值的过程。

目标:

1.将一个连续型变量修改为一组类别值;

2.将误编码的值替换为正确值;

3.基于一组分数线创建一个表示及格/不及格的变量。

逻辑运算符

< 小于
<= 小于或等于
大于
.> = 大于或等于
== 严格等于
!= 不等于
!x 非x
x|y x或y
x & y x和y
isTRUE(x) 测试x是否为TRUE

将示例中的leadership数据几种经理人的连续型年龄变量age重编码为类别型变量agecat(Young,MiddleAged,Elder).将连续型变量变为类别型变量

#将99岁的年龄值重编码为缺失值
leadership$age[leadership$age == 99] <- NA
#语句variable[condition] <- expression 将仅在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"
View(leadership)

上述代码的更紧凑版本。

leadership <- within(leadership,{
  agecat <- NA
  agecat[age>75] <- "Elder"
  agecat[age>=55 & age <= 75] <- "Middle Aged"
  agecat[age<55] <- "Young"
})

函数within()与函数with()类似,不同的是它允许你修改数据框。首先创建了agecat变量,并将每一行都设为缺失值,括号中剩下的语句接下来依次执行,agecat此时只是一个字符型变量。

4.4 变量的重命名
4.4.1.交互式的方式
假设你希望将变 量名manager修改为managerID,并将date修改为testDate,那么可以使用语句

fix(leadership)

4.4.2编程的方式

#将第二列的名字改变
names(leadership)[2] <- "testDate"
#重命名q1到q5为item1到item5
names(leadership)[6:10] <- c("item1","item2","item3","item4","item5")
#names()默认更改列名,若改行名则用row.names()
row.names(leadership)[2] <- "testDate"

4.5 缺失值

在任何规模的项目中,数据都可能由于未作答问题、设备故障等原因造成不完整,在R中,缺失值以符号NA(not available)表示。与SAS等程序不同,R中字符型和数值型数据使用的缺失值符号是相同的。

函数is.na()允许你检测缺失值是否存在。

y <- c(1,2,3,NA)
is.na(y)
将返回c(FALSE FALSE FALSE  TRUE)
#is.na会返回一个相同大小的对象,如果某个元素是缺失值,相应的位置将被改写成TRUE,不是缺失值的位置则为FALSE。
#应用is.na到leadership上
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 

处理缺失值时要主要两件事,第一,缺失值被认为是不可比较的,即便是与缺失值自身的比较。这意味着无法使用比较运算符来检测缺失值是否存在。第二,R并不能把无限的或者不可能出现的数值标记成缺失值。正负无穷分别用Inf和-Inf所标记,因此5/0返回Inf,不可能的值(如sin(Inf))用NaN(not a number)来标记。

4.5.1 重编码某些值为缺失值

如4.3所述,可以用赋值语句将某些值重编码为缺失值。

4.5.2 在分析中排除缺失值

确定了缺失值的位置后,需要在进一步分析数据之前以某种方式删除这些缺失值,原因是含有缺失值的算术表达式和函数的计算结果也是缺失值。

#举例
x <- c(1,2,NA,3)
y <- x[1]+x[2]+x[3]+x[4] 
z <- sum(x) #用is.na 判断,y z均为NA
#通过na.rm=TRUE在计算之前移除NA并使用剩余值进行计算
x <- c(1,2,NA,3)
y <- sum(x,na.rm = T) #返回y的值为6
#使用na.omit()删除不完整的观测,含有NA的行被移除
newdata <- na.omit(leadership)
View(newdata)

删除所有含有NA的观测(称为行删除,listwise deletion)是处理不完整数据集的若干手段之一。如果只有少数NA或者NA仅集中于一小部分观测中,行删除不失为解决NA的一种优秀方法。但如果NA遍布于数据之中,或者一小部分变量中包含大量的NA,行删除可能会提出相当比例的数据。更优秀的处理方法在18章。

4.6 日期值

日期值通常以字符串的形式输入到R中,然后转化为以数值形式存储的日期变量。函数as.Date()用于执行这种转化,其语法为as.Date(x,"input_format"),其中x是字符型数据,input_format则给出了用于读入日期的适当格式。

%d  数字表示的日期,如01-31
%a  缩写的日期名,如Mon
%A  非缩写星期名,如Monday
%m  月份(00-12),如00-12
%b  缩写的月份,如Jan
%B  非缩写的月份,如January
%y  两位数的年份,如07
%Y  四位数的年份,如2007

日期值的默认输入格式为yyyy-mm-dd。语句:

#将默认格式的字符型数据转换为对应日期
strDates <- c("01/05/1965","08/16/1975")
dates <- as.Date(strDates,"%m/%d/%Y")
View(dates)
????
myformat <- "%m/%d/%y"
leadership$date <- as.Date(leadership$date,myformat)

使用指定格式读取字符型变量,并将其作为一个日期变量替换到数据框中。

Sys.Date() ##返回当天的日期
date() ##返回当前的日期和时间

使用函数format(x,format="output_format")来输出指定格式的日期值,并且可以提取日期值中的某些部分。

today <- Sys.Date()
format(today,format="%B %d %Y")
format(today,format="%A")

在日期值上执行算术运算

startdate <- as.Date("2004-02-13")
enddate <- as.Date("2011-01-22")
days <- enddate - startdate
days #得到中间相差多少天
#计算有几周大,最后给的问题是生于周几,没完成
today <- Sys.Date()
dob <- as.Date("1956-10-12")
difftime(today,dob,units = "weeks")

4.6.1 将日期转换成字符型变量

#使用as.character()将日期值转换成字符型
strDates <- as.character(dates)
class(strDates)

4.6.2 更进一步

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()

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

4.8 数据排序

在R中,可以使用order()函数对一个数据框进行排序,默认的排序顺序是升序,在排序变量的前面加一个减号即可得到降序的排列结果。

#创建一个新的数据集,各行按经理人的年龄升序排序。
newdata <- leadership[order(leadership$age),]
View(newdata)
#将各行依女性到男性,同样性别中按年龄升序排序。
attach(leadership)
newdata <- leadership[order(gender,age),]
detach(leadership)
View(newdata)
#将各行依经理人的性别和年龄降序排序
attach(leadership)
newdata <- leadership[order(gender,-age),]
detach(leadership)
View(newdata)

4.9 数据集的合并

4.9.1 向数据框添加列

要横向合并两个数据框(数据集),请使用merge()函数。在多数情况下,两个数据框是通过一个或者多个共有变量进行联结的(即一种内联结,inner join)。如:

#将dataframeA 和dataframeB按照ID进行了合并
total <- merge(dataframeA,dataframeB,by="ID")
#将两个数据框按照ID和Country进行了合并
total <- merge(dataframeA,dataframeB,by=c("ID","Country"))
#如果要直接横向合并两个矩阵或者数据框,并且不需要指定一个公共索引,可以直接使用cbind()函数,前提是每个对象必须拥有相同的行数,以同顺序排序。
total<- cbind(A,B)

4.9.2 向数据框添加行

要想纵向合并两个数据框(添加行),使用rbind()函数,两个数据框必须拥有相同的变量,不过它们的顺序不必一定相同,如果dataframeA中拥有dataframeB中没有的变量,在合并前做如下处理:1.删除dataframeA中的多余变量;2.在dataframeB中创建追加的变量并将其值设为NA

total <- rbind(dataframeA,dataframeB)

4.10 数据集取子集

4.10.1 选入(保留)变量

对数据框中的元素,通过dataframe[row indices,column indices]来访问
#从leadership数据框中选择了6-10列,并将它们保存到了数据框newdata中,将行下标留空表示默认选择所有行。
newdata <- leadership[,c(6:10)]
#与上述等价,引号中的变量名充当了列的下标,因此与上述选择的列是相同的
myvars <- c("q1","q2","q3","q4","q5")
newdata <- leadership[myvars]
# 也可以写为
myvars <- paste("q",1:5,sep = "")
newdata <- leadership[myvars]
View(newdata)

4.10.2 剔除(丢弃)变量

##names(leadership)提取包含所有变量名的字符型向量,%in% c("q3","q4")返回一个逻辑向量,匹配q3或q4的元素值为T,反之为F。
myvars <- names(leadership) %in% c("q3","q4")
#[!myvars]将逻辑值反转,进而选择没有q3或q4的列
newdata <- leadership[!myvars]
View(newdata)
##在知道q3和q4是8th和9th变量的情况下,每一列的下标之前加一个减号表示剔除那一列。
newdata <- leadership[c(-8,-9)]

剔除工作还可以通过如下语句删除。注意NULL与NA(缺失)不同

leadership$q3 <- leadership$q4 <- NULL

4.10.3 选入观测
选择所有30岁以上的男性。方式一:

newdata <- leadership[leadership$gender=="M" & leadership$age > 30,]# [leadership$gender=="M" &leadership$age > 30,]生成TRUE的逻辑比较值,并提取所有行

方式二:使用attach(),就不必再变量名前加上数据框名称了

attach(leadership)
newdata <- leadership[gender=='M' & age > 30,]
detach(leadership)
View(newdata)

将研究范围限定在某一日期范围的观测上

#使用mm/dd/yy将作为字符值读入的日期转换为日期值
leadership$date <- as.Date(leadership$date,"%m/%d/%y")
#创建开始和结束的日期
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2009-10-31")
#选取满足期望的个案
newdata <- leadership[which(leadership$date >= startdate & leadership$date<= enddate),]

4.10.4 subset()函数

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

#1 选择所有age值大于等于35或age值小于24的行,保留了变量q1到q4。若去掉select()则全都保留。
newdata <- subset(leadership,age >=35 | age <24,select = c(q1,q2,q3,q4))
View(newdata)
#2 选择所有25岁以上的男性,并保留了变量gender到q4之间的所有列。
newdata <- subset(leadership,gender=="M" & age >25,select = gender:q4)
View(newdata)

4.10.5 随机抽样

sample()函数能够让你从数据集中(有放回或无放回地)抽取大小为n的一个随机样本。

#从leadership数据集中随机抽取一个大小为3的样本
mysample <- leadership[sample(1:nrow(leadership),3,replace = F),]
View(mysample)

sample()函数中,第一个参数是一个由要从中抽样的元素组成的向量,在这里,这个向量 是1到数据框中观测的数量;第二个参数是要抽取的元素数量,第三个参数表示无放回抽样。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容