《R语言实战》第4章

Posted starjuly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《R语言实战》第4章相关的知识,希望对你有一定的参考价值。

# 第四章 基本数据管理
# 4.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)
q1 <- c(5, 3, 3, 3, 2)
q2 <- c(4, 5, 5, 3, 2)
q3 <- c(5, 2, 5, 4, 1)
q4 <- c(5, 3, 3, 3, 2)
q5 <- c(5, 3, 3, 3, 2)
leadership <- data.frame(manager, date, country, gender, age,
                         q1, q2, q3, q4, q5, stringsAsFactors = FALSE)


# 4.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
# 第二种方式
attach(mydata)
mydata$sumx <- x1 + x2
mydata$meanx <- (x1 + x2)/2
detach(mydata)
# 第三种方式
mydata <- transform(mydata,
                    sumx = x1 + x2,
                    meanx = (x1 + x2)/2)


# 4.3 变量的重编码
# 重编码涉及根据同一个变量和/或其他变量的现有值创建新值的过程
# 语句variable[condition] <- expression将仅在condition的值为TRUE时执行赋值。
# 必须将99岁的年龄值重编码为缺失值
leadership$age[leadership$age == 99] <- NA
leadership$agecat[leadership$age > 75] <- "Elder"
leadership$agecat[leadership$age >= 55 &
                    leadership$age <= 75] <- "Middle Aged"
leadership$agecat[leadership$age < 75] <- "Yong"
# 可以将上面的代码写成更紧凑的
leadership <- within(leadership, 
  agecat <- NA
  agecat[age > 75] <- "Elder"
  agecat[age >= 55 & age <= 75] <- "Middle Age"
  agecat[age < 55] <- "Yong")



# 4.4 变量的重命名
# 如果对现有的变量名称不满意,你可以交互地或者以编程的方式修改它们
install.packages("reshape")
library(reshape)
# 格式:rename(dataframe, c(oldname = "newname”, oldname = "newname"),...)
# 例子:
leadership <- rename(leadership,
                     c(manager = "managerID", date = "testDate"))
# 可以通过names()函数来重命名变量
names(leadership)[2] <- "testDate"
# 类似的方式:
names(leadership)[6:10] <- c("item1", "item2", "item3", "item4", "item5")
# 还原
names(leadership)[6:10] <- c("q1", "q2", "q3", "q4", "q5")





# 4.5 缺失值
# 缺失值以符号NA(Not Available,不可用)表示
# 不可能出现的值(例如,被0除的结果) 通过符号NaN(Not a Number,非数值)来表示
y <- c(1, 2, 3, NA)
is.na(y)
# leadership
is.na(leadership[, 6:10])

# 4.5.2 在分析中排除缺失值
# 由于x中的第3个元素是缺失值,所以y和z也都是NA(缺失值)。
x <- c(1, 2, NA, 3)
y <- x[1] + x[2] + x[3] + x[4]
z <- sum[x]
# 好在多数的数值函数都拥有一个na.rm=TRUE选项,可以在计算之前移除缺失值并使用剩余值进行计算:
y <- sum(x, na.rm = TRUE)
# 可以通过函数na.omit()移除所有含有缺失值的观测。na.omit()可以删除所有含有缺 失数据的行。
newdata <- na.omit(leadership)


# 4.6 日期值
# 日期值通常以字符串的形式输入到R中,然后转化为以数值形式存储的日期变量。函数as.Date()用于执行这种转化。其语法为as.Date(x, "input_format"),其中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。以下语句将默认格式的字符型数据转换为了对应日期
mydates <- as.Date(c("2019-03-13", "2019-01-01"))
# 使用mm/dd/yyyy的格式读取数据
strDates <- c("01/05/2019", "11/22/2020")
dates <- as.Date(strDates, "%m/%d/%Y")
# 转换leadership
myformat <- "%m/%d/%y"
leadership$testDate <- as.Date(leadership$testDate, myformat)
# Sys.Date()可以返回当天的日期,而date()则返回当前的日期和时间。
Sys.Date()
date()
# 格式化日期时间
# 可以使用函数format(x, format="output_format")来输出指定格式的日期值,并且 15 可以提取日期值中的某些部分
today <- Sys.Date()
format(today, format = "%B %d %Y")
# 查看当前的星期名
format(today, format="%A")
# R的内部在存储日期时,是使用自1970年1月1日以来的天数表示的,更早的日期则表示为负 数。这意味着可以在日期值上执行算术运算。例如:
startdate <- as.Date("2018-03-13")
enddate <- as.Date("2019-03-14")
days <- enddate - startdate
days
# 也可以使用函数difftime()来计算时间间隔,并以星期、天、时、分、秒来表示。
today <- Sys.Date()
dob <- as.Date("1994-10-02")
difftime(today, dob, units = "weeks")
format(dob, format = "%A")

# 4.6.1 将日期转换为字符型变量
strDates <- as.character(dates)

# 4.6.2 更进一步
help("as.Date")
help("strftime")



# 4.7 类型转换
# 类型转换函数:名为is.datatype()这样的函数返回TRUE或FALSE,而as.datatype()这样的函数则将其参数转换为对应的类型。
#     判断            转换
# is.numeric()      as.numberic()
# 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-5 转换数据类型
a <- c(1, 2, 3)
is.numeric(a) # 输出:TRUE
is.vector(a)  # 输出:TRUE
# 转为字符串
a <- as.character(a)
a  # 输出:[1] "1" "2" "3"
is.numeric(a)   # 输出:FALSE
is.vector(a)    # 输出:TRUE
is.character(a) # 输出:TRUE



# 4.8 数据排序
# 在R中,可以使用order()函数对一个数据框进行排序。默认的排序顺序是升序。在排序变量的前边加一个减号即可得到降序的排序结果。
# 以下示例使用leadership演示了数据框的排序
# 创建了一个新的数据集,其中各行依经理人的年龄升序排序。语句:
newdata <- leadership[order(leadership$age),]
# 将各行依女性到男性、同样性别中按年龄升序排序。
attach(leadership)
newdata <- leadership[order(gender, age),]
detach(leadership)
# 将各行依经理人的性别和年龄降序排序。
attach(leadership)
newdata <- leadership[order(gender, -age),]
detach(leadership)



# 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)
# 这个函数将横向合并对象A和对象B。为了让它正常工作,每个对象必须拥有相同的行数, 且要以相同顺序排序。
# merge:
total <- merge(leadership, newdata, by = "managerID")
# cbind
total <- cbind(leadership, newdata)

# 4.9.2 添加行
# 要纵向合并两个数据框(数据集),请使用rbind()函数:
# total <- rbind(dataframeA, dataframeB)
# 两个数据框必须拥有相同的变量,不过它们的顺序不必一定相同。如果dataframeA中拥有 dataframeB中没有的变量,请在合并它们之前做以下某种处理:
#   删除dataframeA中的多余变量;
#   在dataframeB中创建爱你追加的变量并将其设置为NA(缺失值)
# 纵向联结通常用于向数据框中添加观测
total <- rbind(leadership, newdata)


# 4.10 数据集取子集
# 4.10.1 选入(保留)变量
# 数 据框中的元素是通过dataframe[row indices, column indices]这样的记号来访问的。例如:
newdata <- leadership[, c(6:10)]
# 从leadership数据框中选择了变量q1、q2、q3、q4和q5,并将它们保存到了数据框newdata 中。将行下标留空(,)表示默认选择所有行。
myvars <- c("q1", "q2", "q3", "q4", "q5")
newdata <- leadership[myvars]
# 也可以如下的方式实现(实现不了,paste函数有问题)
# myvars <- paste("q", 1:5, seq = "")
# nnewdata <- leadership[myvars]

# 4.10.2 剔除(丢弃)变量
# 如果某个变量中有若干缺失值,你可能就想在进一步分 析之前将其丢弃。
# 以下是剔除leadership数据框中的变量q3和q4
myvars <- names(leadership) %in% c("q3", "q4")
newdata <- leadership[!myvars]
# 以下是对上面两句的分析:
# (1) names(leadership)生成了一个包含所有变量名的字符型向量: c("managerID","testDate","country","gender","age","q1", "q2","q3","q4","q5")。
# (2) names(leadership) %in% c("q3", "q4")返回了一个逻辑型向量,names(leadership) 中每个 匹配q3或q4的元素的值为TRUE,反之为FALSE:c(FALSE, FALSE, FALSE, FALSE,FALSE, FALSE, FALSE, TRUE, TRUE, FALSE)。
# (3) 运算符非(!)将逻辑值反转:c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE,FALSE, TRUE)。
# (4) leadership[c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE,TRUE)]选择了逻辑值为TRUE的列,于是q3和q4被剔除了。

# 在知道q3和q4是第8个和第9个变量的情况下,可以使用语句将它们剔除。这种方式的工作原理是,在某一列的下标之前加一个减号()就会剔除那 一列。
newdata <- leadership[c(-8, -9)]
# 相同的变量删除工作亦可通过以下语句完成:
newdata$q1 <- newdata$q2 <- NULL


# 4.10.3 选入观测
# 选入或剔除观测(行)通常是成功的数据准备和数据分析的一个关键方面。
# 代码清单4-6 选入观测
newdata <- leadership[1:3, ]
newdata <- leadership[which(leadership$gender == "M" &
                              leadership$age > 30),]
# 方式二:
attach(leadership)
newdata <- leadership[which(gender == "M" & age > 30),]
detach(leadership)
# 在以上每个示例中,你只提供了行下标,并将列下标留空(故选入了所有列)。在第一个示 例中,你选择了第1行到第3行(前三个观测)。
# 在第二个示例中,你选择了所有30岁以上的男性。让我们拆解这行代码以便理解它。
# (1) 逻辑比较leadership$gender=="M"生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
# (2) 逻辑比较leadership$age > 30生成了向量c(TRUE, TRUE, FALSE, TRUE, TRUE)。
# (3) 逻辑比较c(TRUE, FALSE, FALSE, TRUE, TRUE) & c(TRUE, TRUE, FALSE, TRUE,TRUE)生成了向量c(TRUE, FALSE, FALSE, TRUE, FALSE)。
# (4) 函数which()给出了向量中值为TRUE元素的下标。因此,which(c(TRUE, FALSE,FALSE, TRUE, FALSE))生成了向量c(1, 4)。
# (5) leadership[c(1,4),]从数据框中选择了第一个和第四个观测。这就满足了我们的选取准则(30岁以上的男性)。

# 将研究范围限定在2009年1月1日到2009年12月31日之间收集的观测上。
leadership$testDate <- as.Date(leadership$testDate, "%m/%d/%y")
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2009-12-31")
newdata <- leadership[which(leadership$testDate >= startdate &
                        leadership$testDate <= enddate),]


# 4.10.4 subset()函数
# 选择了所有age值大于等于35或age值小于24的行,保留了变量q1到q4。
newdata <- subset(leadership, age >= 35 | age < 24,
                  select = c(q1, q2, q3, q4))
# 你选择了所有25岁以上的男性,并保留了变量gender到q4(gender、q4和其间所有列)
newdata <- subset(leadership, age > 25 & gender == "M",
                  select = gender:q4)


# 4.10.5 随机抽样
# sample()函数能够让你从数据集中(有放回或无放回地)抽取大小为n的一个随机样本。
# 使用以下语句从leadership数据集中随机抽取一个大小为3的样本:
mysample <- leadership[sample(1:nrow(leadership), 3, replace = FALSE), ]
# sample()函数中的第一个参数是一个由要从中抽样的元素组成的向量。在这里,这个向量 是1到数据框中观测的数量,第二个参数是要抽取的元素数量,第三个参数表示无放回抽样。 sample()函数会返回随机抽样得到的元素,之后即可用于选择数据框中的行。


# 4.11 使用 SQL 语句操作数据框
install.packages("sqldf")
# 代码清单4-7 使用SQL语句操作数据框
library(sqldf)
# 从数据框mtcars中选择了所有的变量(列),保留了那些使用化油器 (carb)的车型(行),按照mpg对车型进行了升序排序,并将结果保存为数据框newdf。参数 row.names=TRUE将原始数据框中的行名延续到了新数据框中。
newdf <- sqldf("select * from mtcars where carb=1 order by mpg",
               row.names = TRUE)
# 输出了四缸和六缸车型每一gear水平的mpg和disp的平均值。
sqldf("select avg(mpg) as avg_mpg, avg(disp) as avg_disp, gear
      from mtcars where cyl in(4, 6) group by gear")

以上是关于《R语言实战》第4章的主要内容,如果未能解决你的问题,请参考以下文章

《R语言实战》第5章

《R语言实战》第2章

R语言实战 第7章

《R语言实战》第1章

《R语言实战》第3章

《R语言实战》第6章