vlambda博客
学习文章列表

R语言系列1:数据结构、数据导入和常用函数

R语言系列1:数据结构、数据导入和常用函数


此文内容为《R语言实战》的笔记,人民邮电出版社出版。

从高中电脑课学VB开始,大一课内开始学习C++,到后来大二为了数模学习Matlab,到大三为了搞深度学习自学Python,到研究生之初学习Stata——选择一门语言对我来说就像是小时候玩冒险岛,到10级的时候是转战士好还是弓箭手好一般的纠结。我查阅了很多B乎的文章,最后觉得可能R比较合适现在的我。

作为从Python转进来R的新手,我把可能会用经常需要用到或经常需要查阅的代码贴上来,主要是为了日后方便查找,就像“字典”一样。推文的顺序与教材不同,为了简洁,我还会删除一些我个人认为不太重要的章节。我还会按照自己的学习进度发布文章,请读者见谅。

本文章仅供学习参考,请勿转载,侵删!


目录

  • 第2章  创建数据集
    • 2.1  数据集的概念
    • 2.2  数据结构
      • 2.2.1 向量
      • 2.2.2 矩阵
      • 2.2.3 数组
      • 2.2.4 数据框
      • 2.2.5 因子
      • 2.2.6 列表
        • A. attach(), detach(), with()
        • B. 实例标识符
    • 2.3  数据的输入
      • 2.3.1 从分隔符文件导入数据
      • 2.3.2 导入Excel数据
      • 2.3.3 导入Stata数据
    • 2.5  处理对象的常用函数

第2章 创建数据集

按照个人要求的格式创建含有研究信息的数据集。在R中,这个任务包括两步:

  • 选择一种数据结构来储存数据
  • 将数据输入或导入到这个数据结构中

2.1 数据集的概念

数据集是由数据构成的一个矩形数组,行表示观测,列表示变量。

2.2 数据结构

R拥有的数据结构有:

  • 标量
  • 向量
  • 矩阵
  • 数组
  • 数据框
  • 列表

在R中,对象(object)是指可以赋值给变量的任何事物;数据框(data frame)是R中用于储存数据的一种结构:列表示标量,行表示观测;因子(factor)是名义型标量或有序变量。

2.2.1  向量

向量是用于储存数值型、字符型或逻辑型数据的一维数组。执行组合功能的函数c()可以用来创建向量:

a <- c(1, 2, 5, 3, 6, -2, 4)b <- c("one", "two", "three")c <- c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)

标量是只含一个元素的向量,例如

f <- 3g <- "US"h <- TRUE

通过在方括号中给定元素所处的位置的数值,可以访问向量中的元素,例如:

a <- c("k", "j", "h", "a", "c", "m")a[3]
## [1] "h"

最后一个语句中使用的冒号用于生成一个数值序列,例如a <- c(2:6)等价于a <- c(2, 3, 4, 5, 6)


2.2.2 矩阵

矩阵是一个二维数组,只是每个元素都有相同的模式(数值型、字符型或逻辑型)。可以通过matrix()创建矩阵,一般使用格式为:

mymatrix <- matrix(vector, nrow=number_of_rows, ncol=number_of_columns, byrow=logical_value, dimnames=list(char_vector_rownames, char_vector_colnames))

其中,vector包含了矩阵的元素,nrowncol用以指定行和列的维数,dimnames包含了可选的、以字符型向量表示的行名和列名。选项byrow则表明矩阵以行填充还是以列填充,默认情况下按行填充(TRUE)。

y <- matrix(1:20, nrow = 5)y
## [,1] [,2] [,3] [,4]## [1,] 1 6 11 16## [2,] 2 7 12 17## [3,] 3 8 13 18## [4,] 4 9 14 19## [5,] 5 10 15 20
cells <- c(1,26,24,28)rnames <- c("R1", "R2")cnames <- c("C1", "C2")mymatrix <- matrix(cells, nrow = 2, dimnames = list(rnames, cnames))mymatrix
## C1 C2## R1 1 24## R2 26 28

我们可以用下标和方括号来选择矩阵中的行和列。X[i,]指定X中的第i行,X[,j]指定X中的第j列。X[i,j]指定第i行第j列个元素。选择多个行和列时,下标i和j可以为数值型向量。

x <- matrix(1:10, nrow = 2, ncol = 5)x
## [,1] [,2] [,3] [,4] [,5]## [1,] 1 3 5 7 9## [2,] 2 4 6 8 10
x[2,]
## [1] 2 4 6 8 10
x[,3]
## [1] 5 6
x[1, c(4,5)]
## [1] 7 9

矩阵都是二维的,和向量类似,矩阵也只能包含一种数据结构。当维度超过2时,可以考虑使用数组;当数据类型超过1种时,可以考虑使用data frame。


2.2.3 数组

数组与矩阵类似,但维度可以大于2,可以通过array创建一个数组:

myarray <- array(vector, dimensions, dimnames)

其中,vector包含了数组中的数据;dimensions是一个数值型向量,给出了维度下标的最大值;dimnames是可选的:

dim1 <- c("A1", "A2")dim2 <- c("B1", "B2", "B3")dim3 <- c("C1", "C2", "C3", "C4")z <- array(1:24, c(2,3,4), dimnames = list(dim1, dim2, dim3))z
## , , C1## ## B1 B2 B3## A1 1 3 5## A2 2 4 6## ## , , C2## ## B1 B2 B3## A1 7 9 11## A2 8 10 12## ## , , C3## ## B1 B2 B3## A1 13 15 17## A2 14 16 18## ## , , C4## ## B1 B2 B3## A1 19 21 23## A2 20 22 24

可见,数组只是矩阵的自然推广,而且数据结构也只能有一种。


2.2.4 数据框

由于不同列可以包含不同模式的数据,数据框的概念比矩阵更为一般。数据框是你会在R中最常见的数据结构。、

数据框可以通过命令data.frame()创建:

mydata <- data.frame(col1, col2, col3,...)

其中的列向量col1col2col3可以为任何类型(字符、数值、逻辑)。每一列的列名可以用函数names指定:

patientID <- c(1, 2, 3, 4)age <- c(24, 34, 28, 52)diabetes <- c("Type1", "Type2", "Type1", "Type1")status <- c("Poor", "Improve", "Excellent", "Poor")patientdata <- data.frame(patientID, age, diabetes, status)patientdata
## patientID age diabetes status## 1 1 24 Type1 Poor## 2 2 34 Type2 Improve## 3 3 28 Type1 Excellent## 4 4 52 Type1 Poor

其中,每一列的数据类型必须一样,但不同列的可以不一样。为了方便讨论,数据框的列有时候被称为变量。

选取数据框的元素有很多种。你可以使用前面提到的方括号的方法,也可以直接指定列名:

patientdata[1:2,]
## patientID age diabetes status## 1 1 24 Type1 Poor## 2 2 34 Type2 Improve
patientdata[,1:2]
## patientID age## 1 1 24## 2 2 34## 3 3 28## 4 4 52
patientdata[c("diabetes", "status")]
## diabetes status## 1 Type1 Poor## 2 Type2 Improve## 3 Type1 Excellent## 4 Type1 Poor

你也可以使用记号 $ 来选取一个给定数据框中的某个特定的变量:

patientdata$age
## [1] 24 34 28 52

如果想生成糖尿病类型diabetes和病情status的列联表,可以使用下面的命令:

table(patientdata$diabetes, patientdata$status)
## ## Excellent Improve Poor## Type1 1 0 2## Type2 0 1 0
A. attach()、detach()和with()

每个变量名前面都键入一次patientdata非常麻烦,所以可以使用attach()detach()with()来简化你的代码。

1. attach  函数。attach() 可以将数据框添加到R的搜索路径中。R遇到一个变量名后,会检查搜索路径中的数据框,例如:


   
     
     
   
summary(patientdata$age)plot(patientdata$patientID, patientdata$age)

就等同于


   
     
     
   
attach(patientdata) summary(age) plot(patientID, age)detach(patientdata)

其中,detach()用于将搜索框从搜索路径中移除。需要注意的是,detach()是可以省略的,但在写程序的时候加上是良好的习惯。

重要的是,如果原始文件中已经存在名为age或者patientID的变量,那么原变量会优先于数据框中的列取得优先权。

2. with  函数。另外一种方法是使用with()函数。可以这么写:


   
     
     
   
with(patientdata, { print(summary(age)) plot(patientID, age)})

这种情况下,{}之间的语句都针对patientdata运行,就不许担心变量名和列名冲突了。

with()的局限性在于,赋值仅在函数的括号内生效。例如:


   
     
     
   
with(patientdata, { stats <- summary(age) stats})stats

是会报错的,因为stats仅仅存在于with()环境中。这时候需要使用特殊赋值 <<- 代替标准的赋值符 <-,就可以把对象保存到 with() 外:

with(patientdata, { stats <<- summary(age) stats})
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 24.0 27.0 31.0 34.5 38.5 52.0
stats
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 24.0 27.0 31.0 34.5 38.5 52.0

相对于attach(),更多的教材推荐使用with(),这只是个人习惯问题。

B. 实例标识符

在数据框中,病人编号(patientID)用于区分不同的个体。在R中,实例标识符(case identifier)可通过数据框操作函数中的rowname选项指定,例如:

patientdata <- data.frame(patientID, age, diabetes, status, row.names = patientID)

那么R就会将patientID作为R标记各类打印输出所用的变量。


2.2.5 因子

变量了可以归结为名义型、有序型或连续型。

  • 名义型变量是没有顺序之分的类别变量,例如糖尿病类型Diabetes(Type1, Type2),即使在数据中前者编码为1、后者编码为2,也不意味着二者是递进关系。

  • 而病情Status(poor, improved, excellent)则是顺序型的。

  • 连续型变量可以呈现为一种某个范围的任意值。

在R中,类别(名义型)变量和有序类别(有序型)变量均称为因子(factor)。因子非常重要,它决定了数据的分析方式和视觉呈现效果。

函数factor()以一个整数向量的形式存储类别值,整数的取值范围为[1,...,k],同时一个由字符串组成的内部向量将映射到这些整数上。例如:

diabetes <- c("Type1", "Type2", "Type1", "Type1")diabetes <- facor(diabetes)

将此向量储存为(1,2,1,1),并在内部将其关联为“Type1=1”、“Type2=2”。针对diabetes的任何分析都会将其作为名义型变量对待。

要表示有序变量,则需要使用factor()函数内的ordered=TRUE,例如:

status <- c("Poor", "Improve", "Excellent", "Poor")status <- c(status, ordered=TRUE)

会把status编码为(3, 2, 1, 3)。对于字符型向量,因子水平默认按照字母顺序创建,即“Poor=3”、“Improved=2”、“Excellent=1”。你也可以通过levels改变因子的顺序:

status <- c("Poor", "Improve", "Excellent", "Poor")status <- c(status, ordered=TRUE, levels=c("Poor", "Improved", "Excellent"))

那么就会将status编码为:“Poor=1”、“Improved=2”、“Excellent=3”

数值型变量可以用levelslabels来编码因子,例如男性编码为1,女性编码为2,那么:

sex <- facotr(sex, levels=c(1,2), labels=c("Male", "Female"))

把变量了转换成一个无序因子。

总的来说:

patientID <- c(1, 2, 3, 4)age <- c(24, 34, 28, 52)diabetes <- c("Type1", "Type2", "Type1", "Type1")status <- c("Poor", "Improve", "Excellent", "Poor")diabetes <- factor(diabetes)status <- factor(status, ordered = TRUE, levels = c("Poor", "Improved", "Excellent"))patientdata <- data.frame(patientID, age, diabetes, status)str(patientdata)
## 'data.frame': 4 obs. of 4 variables:## $ patientID: num 1 2 3 4## $ age : num 24 34 28 52## $ diabetes : Factor w/ 2 levels "Type1","Type2": 1 2 1 1## $ status : Ord.factor w/ 3 levels "Poor"<"Improved"<..: 1 NA 3 1

2.2.6 列表

列表(list)是R数据类型中最为复杂的一种。列表就是一些对象的有序结合,允许你整合若干对象到单个对象名下。可以使用list()创建列表:

mylist <- list(object1, object2, ...)

其对象可以是目前为止提到的任何结构。还可以为列表中的对象命名:

mylist <- list(name1=object1, name2=object2, ...)

例如:

g <- "My First List"h <- c(25:30)j <- matrix(c(1:10), nrow = 2)k <- c("one", "two", "three")mylist <- list(title=g, h, matrix=j, English=k)mylist
## $title## [1] "My First List"## ## [[2]]## [1] 25 26 27 28 29 30## ## $matrix## [,1] [,2] [,3] [,4] [,5]## [1,] 1 3 5 7 9## [2,] 2 4 6 8 10## ## $English## [1] "one" "two" "three"

可以通过双重括号指明某个成分的数字或名称来访问列表中的元素,例如mylist[[3]]mylist[["matirx"]]均表示mylist的第三个元素。对于命名的成分,也可以用mylist$matrix来进行引用,例如:

mylist[[3]]
## [,1] [,2] [,3] [,4] [,5]## [1,] 1 3 5 7 9## [2,] 2 4 6 8 10
mylist[["matrix"]]
## [,1] [,2] [,3] [,4] [,5]## [1,] 1 3 5 7 9## [2,] 2 4 6 8 10
mylist$matrix
## [,1] [,2] [,3] [,4] [,5]## [1,] 1 3 5 7 9## [2,] 2 4 6 8 10

R中有很多函数的运行结果都是以列表的形式返回的,这是一个十分重要的数据结构。


2.3 数据的输入


2.3.1 从带分隔符的文本文件中导入数据

可以使用read.table()从带分隔符的文本中导入数据。此函数可以读入一个表格格式的文件并将其保存为一个数据框,语法为:

mydataframe <- read.table(file, options)

其中,options是控制如何处理数据的选项,请查看help。

2.3.2 导入Excel数据

使用xlsx包可以读取Excel数据,首先在Console运行:


   
     
     
   
install.packages("xlsx")

然后运行:

library(xlsx)read.xlsx(file, sheetIndex, header=TRUE)

其中,file是对应的xlsx文件路径;sheetIndex指定第几张工作表;header指定第一行是否为变量名。详细见help。

2.3.3 导入Stata数据

可以使用readstata13包,然后运行:

library(readstata13)read.dta13(file)

即可。具体的选项请看help。


2.5 处理对象的实用函数

处理对象的常用函数有:

length(object) # 显示对象中元素/成分的数量dim(object) # 显示对象的维度str(object) # 显示某个对象的结构class(object) # 显示对象的类或类型mode(object) # 显示对象的模式names(object) # 显示对象中各成分的名称c(object1,...) # 将对象合并为一个向量cbind(object1,...) # 按列合并对象rbind(object1,...) # 按行合并对象object # 输出某个对象head(object) # 列出某个对象的开始部分tail(object) # 列出某个对象的最后部分ls() # 显示当前对象列表