R语言学习3:数据框处理(1)

本系列是一个新的系列,在此系列中,我将和大家共同学习R语言。由于我对R语言的了解也甚少,所以本系列更多以一个学习者的视角来完成。

参考教材:《R语言实战》第二版(Robert I.Kabacoff),书中所提到的John Cook的优秀博文,关于代码规范的《来自Google的R语言编码风格指南》。

Part 1:变量管理

Section 1:创建变量——transform()

为数据框创建新变量,可以使用数据框的$运算符,如果df$variablevariable不属于原数据框,则会创建一个新的数据框。

mydata <- data.frame(
  x1 = c(2, 2, 6, 4),
  x2 = c(3, 4, 2, 8)
)
mydata$sumx <- mydata$x1 + mydata$x2
mydata$meanx <- mydata$sumx / 2

使用transform()函数,能更方便地创建新变量,其用法是:

mydata <- data.frame(
  x1 = c(2, 2, 6, 4),
  x2 = c(3, 4, 2, 8)
)
mydata <- transform(mydata, 
                    sumx = x1 + x2,
                    meanx = (x1 + x2)/2)

除此外,transform()函数也能方便地对数据框执行修改,生成一个修改后的映像。

Section 2:变量的重编码——within()

变量的重编码,指的是根据变量的现有值创建新值的过程,如分箱、纠正错误值等。

为方便以下内容的示范,使用书中给出的原始数据框:

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

条件赋值语句可以在条件为TRUE时,为向量的相应位置执行赋值,其用法为

variable[condition] <- expression  # 这里condition是一个条件向量

结合within()函数,可以方便地为数据框执行重编码,within()函数的语法与with()类似,但with()只允许方便地调用数据框中的变量,而within()还允许修改数据框。如,为leadership数据框中的agecat执行重编码:

leadership$age[leadership$age == 99] <- NA # 将异常值编码为NA

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

Section 3:变量重命名——names()

对变量名称不满意,可以使用fix(df)函数,交互式地更改变量名称,也可以使用names()函数。如

names(leadership)[2] <- "testDate"
names(leadership)[6:10] <- c("item1", "item2", "item3", "item4", "item5")

或使用plyr包中的rename函数修改变量名。

leadership <- rename(leadership, c(manager="managerID"))

Part 2:值处理

Section 1:缺失值

缺失值以符号NA表示,意为Not Available,它是不可比较的(即使是x == NA也不行,只能用is.na(x))。在R语言中,缺失值与Inf(正无穷)、-Inf(负无穷)、NaN(不是一个数,Not a Number)不同,以上是它们的符号。

需要注意,含有缺失值的算术表达式和函数的计算结果也是缺失值。多值函数一般拥有na.rm参数,如果想要在计算时免除缺失值的影响,需要指定na.rm=T

> x <- c(1, 2, NA, 3)
> sum(x)
[1] NA
> sum(x, na.rm=T)
[1] 6

对于数据框,如果缺失值只集中于一小部分观测,可以使用行删除手段,具体地,可以使用na.omit()函数,对所有含缺失值的观测进行删除。

newdata <- na.omit(leadership)  # 函数生成的是一个映像,不会对原数据框产生影响
newdata

Section 2:日期值——as.Date()

要获得当前的日期,可以使用Sys.Date()函数;要获得当前的日期与时间,可以使用date()函数。

> date()
[1] "Fri Feb 19 13:56:35 2021"
> Sys.Date()
[1] "2021-02-19"

在R语言中,日期值常常是以字符串的形式输入的,然后需要使用as.Date()函数转化成数值形式存储的日期,其语法为

as.Date(x, "input_format")

这里,input_format是用于读入日期的适当格式,默认为yyyy-mm-dd(年月日),其他格式化符号如下表。

image-20210219134409881

对于本例,时间格式mm/dd/yy,所以应当使用如下的修改编码:

myformat <- "%m/%d/%y"  # 编码以字符串形式存储
leadership$date <- as.Date(leadership$date, myformat)

要改变日期的格式以输出,可以使用format()函数,其使用格式是

format(x, format="output_format")
---
> m <- Sys.Date()
> format(m, format="%Y/%m/%d")
[1] "2021/02/19"

计算日期之间的差值,可以使用difftime()函数,其使用格式是

difftime(date1, date2, units)

这里units是时间单位,可以使用"auto", "secs", "mins", "days", "weeks"等。

with(leadership, {
  difftime(date[2], date[1], units = "days")
})

Time difference of 4 days

最后,要将日期转化为字符串,使用as.character()函数。

Section 3:类型转换

要判断某个值是否是某个类型,使用is.datatype()函数;将数值转换为某个类型,使用as.datatype()函数。

image-20210219143244148

其中,is.datatype()返回一个TRUEFALSE,可以用于控制流。

Part 3:数据框处理

Section 1:排序

使用order()函数可以对向量进行排序,order()会对向量重新编码,接受若干个等长向量分别作为排序的有序关键字。

> x <- c("a", "e", "d", "d", "c", "b")
> y <- c(6, 5, 4, 3, 2, 1)

> order(x)
[1] 1 6 5 3 4 2
> order(x, y)  # y作为第二排序标准
[1] 1 6 5 4 3 2

对数据框,也可以使用order()函数作为条件排序,其原理是数据框可以按照一个有序向量进行排序。

with(leadership, {
  newdata2 <<- leadership[order(gender, -age), 1:5]
})

> newdata2

  managerID       date country gender age
2         2 2014-10-28      US      F  45
3         3 2014-10-01      UK      F  25
5         5 2014-05-01      UK      F  NA
4         4 2014-10-12      UK      M  39
1         1 2014-10-24      US      M  32

注意,如果想要呈现完整的数据框,[contidion, ]中逗号是不能省略的。

Section 2:数据框合并

横向合并:即实现两个数据框的内连接,通过一个或多个共有变量,可以使用merge()函数,其用法为

total <- merge(dataframeA, dataframeB, by="ID")  # by指定共有字段

如果不需要考虑外键,只是简单地横向合并,可以使用cbind()函数,这要求每个对象拥有相同的行数,以相同的顺序排序。

纵向合并:即向数据框中增加观测值,可以使用rbind()函数,这要求两个数据框拥有相同的变量个数(对顺序没有要求)。

total <- rbind(dataframeA, dataframeB)

如果两个数据框中变量不同,需要进行预处理:要么删除dataframeA中的多余变量,要么在dataframeB中创建追加的变量,并将其值设为NA

Section 3:数据框取子集

选入变量:使用dataframe[, colindex]即可,这里colindex是变量的索引。事实上,如果需要保留全部观测值,可以直接使用dataframe[colindex]而并不需要逗号。另外,列索引也可以用变量名,如

myvars <- c("q1", "q2", "q3", "q4", "q5")
newdata <- leadership[myvars]

> newdata

  q1 q2 q3 q4 q5
1  5  4  5  5  5
2  3  5  2  5  5
3  3  5  5  5  2
4  3  3  4 NA NA
5  2  2  1  2  1

删除变量:可以使用如下的语句来删除q4q5两个变量。

myvars <- names(leadership) %in% c("q4", "q5")
newdata <- leadership[!myvars]

这里,myvars是一个逻辑变量,除了q4q5T以外其他地方都是F,因此取反,表示除了q4q5F外其他都是T(需要保留)。

另外,如果知道q4q5是第9、第10个变量,可以简单使用

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

进行删除。

选入观测:选入观测也可以使用逻辑变量。现在,选入观测时间在2009-01-012014-10-20之间的观测值,这里which

startdate <- as.Date("2009-01-01")
enddate <- as.Date("2014-10-20")
newdata <- leadership[leadership$date >= startdate & leadership$date <= enddate, ]  # 逗号必须保留

选择数据框的子集,最简单的方法是使用subset()函数,它可以一次性完成以上的功能,其使用格式如下:

subset(x, subset, select)

这里,x是要传入的数据框,subset是要保留观测的逻辑向量,select是要保留变量的向量。

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

> newdata
  gender age q1 q2 q3 q4
1      M  32  5  4  5  5
4      M  39  3  3  4 NA

可以看到,保留变量的向量可以直接用from:to表达式,且fromto可以不必是数值。

如要随机抽取观测,可以使用sample()函数,其用法是

sample(x, size, replace=FALSE)

这里,x表示抽样元素组成的向量,size表示要抽取的元素数量,replace表示是否是有放回抽样。要是从数据集中抽样,可以如此使用:

newsample <- leadership[sample(1:nrow(leadership), 3, replace=F), ]

Section 4:使用SQL查询

如果是较大的数据集,可以使用SQL语句进行查找,这依赖于sqldf库中的sqldf函数。

library(sqldf)
attach(mtcars)
search <- "SELECT * FROM mtcars WHERE carb=1 ORDER BY mpg"
newdf <- sqldf(search, row.names=T)

sqldf中还有许多可选择的参数,如stringsAsFactorsrow.names等。

posted @ 2021-02-19 16:14  江景景景页  阅读(763)  评论(0编辑  收藏  举报