一、R语言—数据集创建
1. 向量
向量(vector)是用于存储数值型、字符型、逻辑型数据的一维数组。标量可以看作是 只含有一个元素的向量。
函数c( )可用来创建向量,例如:
In [2]:x1 <- c(2, 4, 1, -2, 5)
x2 <- c("one", "two", "three")
x3 <- c(TRUE, FALSE, TRUE, FALSE)
这里 x1 是数值型向量,x2 是字符型向量,而 x3 是逻辑型向量。每一个向量中的数据类型必须一致。
如果想创建有规律的向量,R 提供了一些简便的操作和函数,例如:
In [3]:x4 <- 1:5 # 等价于x4 <- c(1, 2, 3, 4, 5)
x5 <- seq(from = 2, to = 10, by = 2) # 等价于x5 <- c(2, 4, 6, 8, 10)
x6 <- rep("a", times = 4) # 等价于x6 <- c("a", "a", "a", "a")
有时候我们只想使用向量中的某个部分,即选取向量的子集。
假设有一个从 3 到 100 的步长为 7 的整数向量,那么第5 个数的值是多少呢?
In [4]:x <- seq(from = 3, to = 100, by = 7)
x
3 10 17 24 31 38 45 52 59 66 73 80 87 94
In [5]:x[5]
31
在方括号“[ ]”中的数字被称为 下标,它指定向量的索引位置。在上面的命令里,x[5] 表示向量的第 5 个元素,其值为 31。
下面的命令显示向量的第 4、第 6 和第 7 个元素:
In [6]:x[c(4, 6, 7)]
24 38 45
下标中的向量可以取负值,表示去除指定位置上的元素。
例如,要去掉 x 的前4 个元素,可以输入下面的代码(注意命令里的括号):
In [7]:x[-(1:4)]
31 38 45 52 59 66 73 80 87 94
R 中的运算都是向量化的,例如:
In [8]:weight <- c(68, 72, 57, 90, 65, 81)
height <- c(1.75, 1.80, 1.65, 1.90, 1.72, 1.87)
bmi <- weight / height ^ 2
bmi
22.2040816326531 22.2222222222222 20.9366391184573 24.9307479224377 21.9713358572201 23.1633732734708
在上面计算 bmi 的过程中,运算符“^”被循环使用了,所以计算的结果仍然是一个向量。
如果参与运算的向量的长度不一致,R 会自动补全后计算,同时给出警告信息 。
In [9]:a <- 1:5
b <- 1:3
a + b
Warning message in a + b:
“longer object length is not a multiple of shorter object length”
2 4 6 5 7
In [10]:length(bmi) # 计算向量bmi的长度
mean(bmi) # 计算向量bmi的均值
var(bmi) # 计算向量bmi的样本方差
sd(bmi) # 计算向量bmi的样本标准差- c(1, 2, 1, 1, 2, 1, 2)
6
22.5714000044102
1.84126459887427
1.35693205389005
常用的统计函数
| 函数 | 描述 |
|---|---|
| length(x) | 求 x 中元素的个数 |
| mean(x) | 求 x 的算术平均值 |
| median(x) | 求 x 的中位数 |
| var(x) | 求 x 的样本方差 |
| sd(x) | 求 x 的样本标准差 |
| range(x) | 求 x 的全距 |
| min(x) | 求 x 的最小值 |
| max(x) | 求 x 的最大值 |
| quantile(x) | 求 x 的分位数 |
| sum(x) | 求 x 中所有元素的和 |
| scale(x) | 将 x 标准化 |
2. 因子
一般来说,变量有数值型、名义型和有序型之分。名义型变量是没有顺序关系的分类变量,例如人的性别、血型、民族等。而有序型变量是有层级和顺序关系的分类变量,如患者的病情(较差、好转、很好)。名义型变量和有序型变量在 R 中称为因子(factor)。 因子在 R 中非常重要,它决定了数据的展示和分析方式。数据存储时因子经常以整数向量形式存储。
所以在进行数据分析之前,经常需要将它们用函数 factor( ) 转换为因子。例如:
sex <- c(1, 2, 1, 1, 2, 1, 2)
sex.f <- factor(sex,
levels = c(1, 2),
labels = c("Male", "Female"))
sex.f
Male Female Male Male Female Male Female
Levels: 'Male' 'Female'上面的命令先定义了一个变量 sex 表示性别,假设其取值 1 表示男性,2 表示女性。接着用函数 factor( ) 将变量 sex 转换成了因子并存为对象 sex.f,其中参数 levels 表示原变量的分类标签值,参数 labels 表示因子取值的标签。注意,这两个参数在赋值时需要一一对应,R 会将它们相关联。因子型变量与一般的字符型变量的区别就是它有一个水平(level)属性。
因子的属性可以使用函数 levels( ) 查看:
levels(sex.f)
'Male' 'Female'
改变因子水平的排列顺序 → 改变参考组
在统计模型中,对于因子型变量,R 会将其第一个水平当作参考组。很多时候我们需要改变因子水平的排列顺序以改变参考组,这可以通过两种方法实现。
第一种方法是在函数 factor( ) 中改变参数 levels 和 labels 的排列顺序,例如:
In [13]:sex.f1 <- factor(sex, levels = c(2, 1), labels = c("Female", "Male"))
sex.f1
Male Female Male Male Female Male Female
Levels: 'Female' 'Male'第二种方法是使用函数 relevel( ):
sex.f1 <- relevel(sex.f, ref = "Female")
sex.f1
Male Female Male Male Female Male Female
Levels: 'Female' 'Male'
有序因子:ordered = TRUE
要表示有序因子,需要在函数 factor ( ) 里指定参数ordered = TRUE。例如:
In [15]:status <- c(1, 2, 2, 3, 1, 2, 2)
status.f <- factor(
status,
levels = c(1, 2, 3),
labels = c("Poor", "Improved", "Excellent"),
ordered = TRUE
)
status.f
Poor Improved Improved Excellent Poor Improved Improved
Levels: 'Poor' 'Improved' 'Excellent'3. 矩阵
矩阵(matrix)是一个由行和列组成的二维数组。矩阵里的每个元素具有相同的模式(数值型、字符型或逻辑型)。在大多数情况下,矩阵里的元素是数值型的,它具有很多数学特性和运算方式,可以用来进行统计计算,例如因子分析、广义线性模型等。
创建:matrix( )
函数 matrix( ) 常用于创建矩阵,例如:
M <- matrix(1:6, nrow = 2)
M
| 1 | 3 | 5 |
| 2 | 4 | 6 |
R 会根据向量的长度和参数 nrow 设定的行数自动计算列数。参数 byrow 默认为 FALSE,即按列将数值进行排列, 如果需要按行排列,只需将参数 byrow 设为TRUE。 常见的矩阵运算都可以在R 中实现,如矩阵加法、矩阵乘法、求逆矩阵、矩阵转置、求方阵的行列式、求方阵的特征值和特征向量等。
相乘:%*%
矩阵乘法中要求第一个矩阵的列数等于第二个矩阵的行数,其运算符为 %*%。 先创建两个矩阵:
mat1 <- matrix(1:6, nrow = 3)
mat1
mat2 <- matrix(5:10, nrow = 2)
mat2
| 1 | 4 |
| 2 | 5 |
| 3 | 6 |
| 5 | 7 | 9 |
| 6 | 8 | 10 |
# 函数dim( )可以得到矩阵的维数,即行数和列数
dim(mat1)
dim(mat2)
3 2
2 3
结果表明,mat1 是一个 3 行 2 列的矩阵,mat2 是一个 2 行 3 列的矩阵,因此它们可以相乘,结果应该是一个 3 行 3 列的矩阵。
In [19]:mat1 %*% mat2
| 29 | 39 | 49 |
| 40 | 54 | 68 |
| 51 | 69 | 87 |
转置:t( )
矩阵的转置运算就是把矩阵的行和列互换。例如,求矩阵 mat1 的转置矩阵:
In [20]:t(mat1)
| 1 | 2 | 3 |
| 4 | 5 | 6 |
行列式和逆矩阵:det( )、solver( )
求方阵的行列式和逆矩阵分别可以使用函数 det( ) 和函数 solve( ) 实现,例如:
mat3 <- matrix(1:4, nrow = 2)
det(mat3)
-2
按行、列求和或者求平均:rowSums、colSums、rowMeans、ColMeans
例如:
In [22]:rowSums(mat1)
colSums(mat1)
rowMeans(mat1)
colMeans(mat1)
5 7 9
6 15
2.5 3.5 4.5
2 5
4. 数组
通常所说的数组(array)指的是多维数组,它与矩阵类似,但是维数大于 2。数组有一个特殊的维数(dim)属性。 下面的命令给一个向量加上维数后定义了一个数组,请注意数值的排列顺序。 ?? 由于 notebook 上显示的数组不太美好,建议使用 print()。以下代码在显示数组时会额外加上 print()。
A <- 1:24
dim(A) <- c(3, 4, 2)
A # notebook 上数组显示不太正常,使用 print() 可以解决
print(A)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
, , 2
[,1] [,2] [,3] [,4]
[1,] 13 16 19 22
[2,] 14 17 20 23
[3,] 15 18 21 24
上面的数组还可以通过函数 array( ) 创建,并给各个维度添加名称和标签。
dim1 <- c("A1", "A2", "A3")
dim2 <- c("B1", "B2", "B3", "B4")
dim3 <- c("C1", "C2")
print(array(1:24, dim = c(3, 4, 2), dimnames = list(dim1, dim2, dim3)))
, , C1
B1 B2 B3 B4
A1 1 4 7 10
A2 2 5 8 11
A3 3 6 9 12
, , C2
B1 B2 B3 B4
A1 13 16 19 22
A2 14 17 20 23
A3 15 18 21 24
5. 列表
列表(list)是 R 中最灵活也最复杂的一种数据结构,它可以由不同类型的对象混合组成。例如,它可以是向量、数组、表格和任意类型对象的组合。
In [25]:list1 <- list(a = 1, b = 1:5, c = c("red", "blue", "green"))
list1
- $a
- 1
$b
1 2 3 4 5
- $c
- 'red' 'blue' 'green'
6. 数据框
数据框(dataframe)是一个由行和列组成的二维结构,其中行表示观测(observation)或记录(record),列表示变量(variable)或指标(indicator)。数据框与 Excel、SAS 和SPSS 中的数据集类似。数据框看起来与矩阵很相似,而且矩阵的很多操作也适用于数据框,如子集的选择。 与矩阵不同的是,数据框里不同的列可以是不同模式(数值型、字符型等)的数据。数据框可以通过函数 data.frame( ) 创建。例如,下面的代码创建了一个包含 5 个观测对象、4 个变量的数据框:
In [29]:ID <- 1:5
sex <- c("male", "female", "male", "female", "male")
age <- c(25, 34, 38, 28, 52)
pain <- c(1, 3, 2, 2, 3)
pain.f <- factor(pain, levels = 1:3, labels = c("mild", "medium", "severe"))
patients <- data.frame(ID, sex, age, pain.f)
patients
| ID | sex | age | pain.f |
|---|---|---|---|
| 1 | male | 25 | mild |
| 2 | female | 34 | severe |
| 3 | male | 38 | medium |
| 4 | female | 28 | medium |
| 5 | male | 52 | severe |
数据框本质上也是一种列表,要显示或使用数据框的某一变量(列),可以使用 $ 符号加上变量名。例如:
patients$age
mean(patients$age)
25 34 38 28 52
35.47. 数据类型的转换:is.、as.
在进行数据分析时,分析者需要对数据的类型熟稔于心,因为数据分析方法的选择与数据的类型是有密切联系的。R 提供了一系列用于判断某个对象的数据类型的函数,还提供了将某种数据类型转换为另一种数据类型的函数。这些函数都存在于基本包 base 里,下面列出了其中的一部分常用函数:
数据类型的判断与转换函数
| 判断 | 转换 |
|---|---|
| is.numeric( ) | as.numeric( ) |
| is.character( ) | as.character( ) |
| is.logical( ) | as.logical( ) |
| is.factor( ) | as.factor( ) |
| is.vector( ) | as.vector( ) |
| is.matrix( ) | as.matrix( ) |
| is.array( ) | as.array( ) |
| is.data.frame( ) | as.data.frame( ) |
| is.list( ) | as.list( ) |
| is.table( ) | as.table( ) |
以 is. 开头的函数的返回值为 TRUE 或 FALSE,而以 as. 开头的函数将对象转换为相应的类型。
8. 获取其他格式的数据
8.1 txt 与csv 格式
如果数据来源是一个用 Windows 记事本或其他纯文本编辑器所创建的 ASCII 格式文件,我们可以使用函数 read.table( ) 读取其中的数据,返回的是一个数据框。
write.table(patients, file = "patients.txt", sep = "\t", row.names = FALSE)
patients.data <- read.table("patients.txt", header = TRUE)
patients.data
| ID | sex | age | pain.f |
|---|---|---|---|
| 1 | male | 25 | mild |
| 2 | female | 34 | severe |
| 3 | male | 38 | medium |
| 4 | female | 28 | medium |
| 5 | male | 52 | severe |
在电子表格和数据库应用中经常会生成带分隔符的文本文件,其中.csv 文件是用逗号分隔取值(Comma Separated Values)。函数 read.csv( ) 是函数 read.table( ) 的一个变体,专用于读取 .csv 文件。 需要注意的是,read.table( ) 和 read.csv( ) 两个函数中参数的默认值是不同的。在函数 read.table( ) 中,参数 header 默认值为 FALSE,即认为文件第一行开始就是数据而非变量名。而在函数 read.csv( )中,参数 header 默认值为 TRUE。因此,在读入数据前,建议先打开原始文件进行查看,然后设置恰当的参数正确地读入数据。例如:
write.csv(patients, "patients.csv", row.names=FALSE)
patients.data <- read.csv("patients.csv")
patients.data
| ID | sex | age | pain.f |
|---|---|---|---|
| 1 | male | 25 | mild |
| 2 | female | 34 | severe |
| 3 | male | 38 | medium |
| 4 | female | 28 | medium |
| 5 | male | 52 | severe |
8.2 xls 或 xlsx 格式
读取电子表格数据有很多种方式,其中最简单的方式是在 Excel 中将数据文件另存为一个逗号分隔(.csv)文件,然后用上述读取.csv 文件的方法将其读入R。还可以借助第三方包(例如 openxlsx 包、readxl 包和 gdata 包)直接读取 xlsx 或 xls 格式的数据文件。
In [40]:library(openxlsx)
write.xlsx(patients, "patients.xlsx")
patients.data <- read.xlsx("patients.xlsx", sheet = 1)
patients.data
| ID | sex | age | pain.f | |
|---|---|---|---|---|
| 1 | 1 | male | 25 | mild |
| 2 | 2 | female | 34 | severe |
| 3 | 3 | male | 38 | medium |
| 4 | 4 | female | 28 | medium |
| 5 | 5 | male | 52 | severe |
8.3 导出数据
由于 R 主要用于数据分析,导入文件比导出文件更常用,但有时我们也需要将数据或分析结果导出。函数 write.table( ) 和 write.csv( ) 可以分别将数据导出到一个 .txt 文件和 .csv 文件。
此外,函数 save( ) 可以将工作空间中的指定对象保存为以 .rdata 为扩展名的 R 数据文件。例如:
save(patients.data, file = "patients.rdata")
rdata 格式文件占用空间小,用 R 读入速度很快。建议在导入其他格式的数据并整理好后,将其保存为 rdata 格式。要导入这种格式的数据,只需调用 load( ) 函数。
load("patients.rdata")
8.4 用 rio 包导入和导出数据
R 中的 rio 包以提供一个类似万能工具的包为目标,用统一的 import( ) 函数和 export( ) 函数简化了用户导入和导出数据的工作。此外,该包里的 convert( ) 函数可以实现不同文件格式之间的转换。rio 包支持多种文件格式,包括 SAS、SPSS、Stata、Excel、MATLAB、Minitab 等其他软件中使用的数据文件格式。 下面以 datasets 包里面的数据集 infert 为例介绍 rio 包的几个常用功能。
library(rio)
data("infert")
str(infert)
'data.frame': 248 obs. of 8 variables:
$ education : Factor w/ 3 levels "0-5yrs","6-11yrs",..: 1 1 1 1 2 2 2 2 2 2 ...
$ age : num 26 42 39 34 35 36 23 32 21 28 ...
$ parity : num 6 1 6 4 3 4 1 2 1 2 ...
$ induced : num 1 1 2 2 1 2 0 0 0 0 ...
$ case : num 1 1 1 1 1 1 1 1 1 1 ...
$ spontaneous : num 2 0 0 0 1 1 0 0 1 0 ...
$ stratum : int 1 2 3 4 5 6 7 8 9 10 ...
$ pooled.stratum: num 3 1 4 2 32 36 6 22 5 19 ...
函数 str( ) 常用于查看数据集的大小(观测的记录数及变量个数),以及各个变量的类型。从上面的输出可以看出,infert 是一个包含 248 个观测记录、每个记录有 8 个变量的数据框。 运行下面的命令将此数据框导出为 .csv 文件:
export(infert, "infert.csv")
在当前工作目录中可以找到刚才导出的名为 infert.csv 的数据文件。运行下面的命令将该文件从 .csv 文件转换成 .sav 文件:
convert("infert.csv", "infert.sav")
然后用函数 import( ) 把上面生成的 .sav 文件导入 R 中,并命名为 infert.data:
infert.data <- import("infert.sav")
函数(或数据集):
| 函数(或数据集) | 来源包 | 功能描述 |
|---|---|---|
| as.character( ) | base | 将对象转换为字符串 |
| as.factor( ) | base | 将对象转换为因子 |
| as.numeric( ) | base | 将对象转换为数值 |
| array( ) | base | 创建数组 |
| bacteria | MASS | 数据集 |
| boxplot( ) | graphics | 绘制箱线图 |
| c( ) | base | 创建向量 |
| class( ) | base | 获取对象的类型 |
| colMeans( ) | base | 按列求均值 |
| colSums( ) | base | 按列求和 |
| convert( ) | rio | 转换数据格式 |
| data( ) | utils | 加载R |
| data.frame( ) | base | 创建数据框 |
| det( ) | base | 求矩阵的行列式 |
| dim( ) | base | 获取对象的维数 |
| export( ) | rio | 将数据框导出为一个数据文件 |
| factor( ) | base | 将一个向量转换为因子 |
| hist( ) | graphics | 绘制直方图 |
| import( ) | rio | 导入数据文件 |
| infert | datasets | 数据集 |
| iris | datasets | 数据集 |
| is.logical( ) | base | 判断对象是否为逻辑型 |
| is.numeric( ) | base | 判断对象是否为数值型 |
| is.vector( ) | base | 判断对象是否为向量 |
| length( ) | base | 获取对象的长度 |
| levels( ) | base | 获取因子的水平 |
| list( ) | base | 创建列表 |
| matrix( ) | base | 创建矩阵 |
| read.csv( ) | utils | 读取.csv |
| read.dta( ) | foreign | 读取Stata |
| read.epiinfo( ) | foreign | 读取EpiData |
| read.spss( ) | foreign | 读取SPSS |
| read.table( ) | utils | 读取文本格式数据文件 |
| read.xlsx( ) | openxlsx | 读取Excel |
| read.xport( ) | foreign | 读取SAS |
| relevel( ) | stats | 改变因子水平的顺序 |
| rep( ) | base | 将对象重复显示 |
| rbinom( ) | stats | 生成服从二项分布的随机数 |
| rnorm( ) | stats | 生成服从正态分布的随机数 |
| rpois( ) | stats | 生成服从Poisson |
| runif( ) | stats | 生成服从均匀分布的随机数 |
| rowMeans( ) | base | 按行求均值 |
| rowSums( ) | base | 按行求和 |
| save( ) | base | 将对象保存为R |
| sd( ) | stats | 求样本标准差 |
| seq( ) | base | 生成有规则的序列 |
| set.seed( ) | base | 设置生成随机数的种子数 |
| solve( ) | base | 求解矩阵方程 |
| str( ) | utils | 显示对象的内部结构 |
| t( ) | base | 矩阵的转置运算 |
| var( ) | stats | 求样本方差 |
| View( ) | utils | 打开数据浏览窗口 |
| write.csv( ) | utils | 将数据框导出到一个.csv |
| write.table( ) | utils | 将数据框导出到一个文本文件 |