在正式分析数据前,我们通常需要先预处理一下数据,比如筛选有效样本,定义变量格式,处理缺失值等,目的是把数据整理成比较清洁的形式,便于后续处理,而R的tidyverse
系列工具包针对此提供了丰富多样的处理方案。本篇内容主要介绍常用的数据导入函数和dplyr
包中的一些重要函数。
1 数据导入
R支持多种数据格式,最常见的是csv和excel文件。
1.1 导入csv文件
read.table()
和read.csv()
是R基础包utils
中的函数(基础包会自动加载,相关函数可以直接调用),二者均可读取csv格式文件。
data <- read.table(file, header = FALSE, sep = "")
data <- read.csv(file, header = TRUE, sep = ",")
两个函数的主要参数均为前三个参数,其中第一个参数file为文件地址,第二个参数header表示是否以首行为标题,第三个参数sep表示分列符。两个函数后两个参数的默认值不同,
read.table()
默认不以首行为标题、不分列,read.csv
默认以首行为标题、以逗号,
分列。
csv本身是以逗号为分隔的文件,是否以首行为标题要根据实际情况。假设用fileaddress表示文件地址,那么两个函数导入csv数据的代码分别如下:
# 首行为标题
data <- read.table(fileaddress, header = TRUE, sep = ",")
data <- read.csv(fileaddress)
# 首行不为标题
data <- read.table(fileaddress, sep = ",")
data <- read.csv(fileaddress, header = FALSE)
1.2 导入excel文件
R基础包中没有直接能读取excel文件的函数,需要借用其他功能包,常用的有readxl
和xlsx
两个工具包,对应的函数分别是read_excel()
和read.xlsx()
。
library(readxl)
data <- read_excel(path, sheet = NULL, col_names = TRUE)
根据excel文件的具体格式可以选择使用
read_xls()
和read_xlsx()
函数,当批量化读取数据且两种格式并存时,可以使用通用函数read_excel()
。path参数表示文件地址,sheet参数表示工作表序号,无默认值,col_names参数表示列名,默认为“是”。
xlsx
包安装比较麻烦,需要先安装Java程序。首先进入Java官网,点击“所有Java下载”,下拉网页找到对应的Java脱机版本,需要注意的是Java的位数必须与使用的R的位数一致,比如均为64位或32位。Java安装文件夹默认为“C:\Program Files\Java\jre1.8.0_271”(最后的文件夹编号视版本而变化)不要改动。安装成功后再在R中运行以下代码:
install.packages("rJava")
install.packages("xlsxjars")
install.packages("xlsx")
Sys.setenv(JAVA_HOME="C:\\Program Files\\Java\\jre1.8.0_271")
Sys.setenv()
用于设置系统环境变量,运行后需要重新启动R才能生效。重启后就可以正常加载xlsx
了。read.xlsx()
的主要参数如下:
data <- read.xlsx(file, sheetIndex, header = TRUE, encoding = "unknown")
2 数据筛选、转换等操作
在数据导入后,一般会首先进行删除无效样本、变量,利用原有变量生成新变量等操作,常用函数名称及其功能如下:
filter()
:按行筛选样本;select()
:按列选择变量;mutate
:根据一个或多个变量生成新变量或重定义已有变量,原变量仍然保留;transmute()
:根据一个或多个变量生成新变量或重定义已有变量后,其他变量不再保留。
library(tidyverse)
data <- mtcars # 假设导入的数据
summary(data) # 查看data的变量和数据特征
data %>%
filter(cyl == 6) %>% # 样本筛选操作,只保留变量cyl为6的样本
select(mpg, disp, hp) %>% # 变量选择操作,只保留这三个变量
select(-mpg) %>% # 变量反向选择操作,删去此变量,其他变量保留
mutate(newvar = disp * hp) -> newdata # 生成新变量操作
newdata %>%
transmute(newvar = disp * hp) -> newdata2
3 数据框拼接、连接操作
数据框的合并是指将两个数据框整合成一个数据框,分为直接按行或列拼接和按共同变量连接两种,常用的函数名称及功能如下:
bind_cols
:增加列合并,将两个数据框相同行拼接成同一行,要求它们行数相同,即
行
列和
行
列的两个数据框合并成
行
列的一个数据框;bind_rows
:增加行合并,要求两个数据框列数相同。
R基础包中的
cbind()
和rbind()
函数也有类似功能,但运行速度较慢。
left_join()
:左连接,即以第一个数据框为参照;right_join()
:右连接,即以第二个数据框为参照。
这两个连接方案会保留参照数据框的所有行,而非参照数据框只保留能匹配到参照数据框的行,参照数据框不能匹配非参照数据框的行对应非参照数据框的变量记为
NA
;无论是左连接 还是右连接,合并后的数据框变量排序都是第一个数据框的原变量在前,第二个数据框的原变量在后;
如果非参照数据框有多行与参照数据框的一行对应,那么合并后的数据框相比于参照数据框会多出若干行以一一连接这些行。
full_join()
:全连接,保留两个数据框所有的行,不能匹配的行对应变量记为NA
;inner_join()
:内连接,只保留两个数据框能匹配的行;semi_join()
:半连接,保留第一个数据框能与第二个数据框匹配的内容,但不把第二个数据框的变量加入合并的数据框;anti_join()
:反向连接,保留第一个数据框不能与第二个数据框匹配的内容。
library(tidyverse)
# 准备两个数据框,ID为公共变量
df1 <- mtcars %>%
slice(1 : 10) %>%
select(mpg) %>%
mutate(ID = c(1 : 10))
df2 <- iris %>%
slice(1 : 12) %>%
select(Sepal.Length) %>%
mutate(ID = floor(runif(12, min = 2, max = 11)))
# left_join
left_join(df1, df2, by = "ID")
# 公共变量名称在两个数据框中不同
df11 <- rename(df1, ID1 = ID)
df22 <- rename(df2, ID2 = ID)
left_join(df11, df22, by = c("ID1" = "ID2"))
# right_join
right_join(df1, df2, by = "ID")
# full_join
full_join(df1, df2, by = "ID")
# inner_join
inner_join(df1, df2, by = "ID")
# semi_join
semi_join(df1, df2, by = "ID")
# anti_join
anti_join(df1, df2, by = "ID")
4 命名、排序、分组等操作
rename
:重命名变量;arrange()
:按变量进行行排序,优先级高的变量写在前面,默认升序,降序时使用desc(var)
;relocate()
:改变变量的列顺序;group_by()
:按变量分组;ungroup()
:取消分组;summarise()
:汇总操作。
summary(mtcars)
mtcars %>%
select(mpg, disp, hp, cyl) %>%
slice(1 : 10) %>%
rename(mpg1 = mpg) %>%
arrange(disp, desc(hp)) %>% # 按disp升序、hp降序排序
relocate(hp, disp) %>% # 将变量hp移到disp前面
group_by(cyl) %>% # 按cyl分组
mutate(mean = mean(disp)) %>% # 按以上分组求disp的均值
ungroup() -> data # 取消分组
data %>%
group_by(cyl) %>%
summarise(mean = mean(disp), n = n()) # 汇总