今天给大家介绍R语言中的数据结构,数据结构就是存储数据的形式。数据结构的概念非常重要,也是必须要理解的内容。

今天的内容可以说是R语言入门中最重要的基础知识了,但同时对于没有任何计算机基础的人来说,也是超级抽象,因为这部分内容和我们医学生日常接触的内容没有任何关系,从这一章开始,也是正式进入了R语言的核心内容。

如果觉得这部分内容太过抽象,难以理解,也不用担心,因为这部分内容虽然复杂,但主要是概念性的内容,有很多东西不用急于理解,只要记住即可。

学习编程就是要多敲代码,大家跟着多敲一敲,自然就记住且理解了。

我们常说的数据操作其实就是对各种数据结构进行操作,你在平常碰到的绝大多数数据清理/整理等问题,说白了就是对数据框、向量、列表等各种结构进行处理,所以这部分内容非常重要。

因为不同的结构有不同的操作方法。比如第5章中读取的brca_clin,其实就是一个数据框(data.frame),我们要做的就是对这个数据框进行各种操作。

R拥有许多用于存储数据的对象类型,包括标量、向量、矩阵、数组、数据框和列表等。它们在存储数据的类型、创建方式、结构复杂度,以及对它们进行操作的方法等均有所不同。下图给出了这些数据结构的一个示意图。

https://mmbiz.qpic.cn/mmbiz_png/tpAC6lR84Ric4b9cDkV8CHoApYShJsTB1d5Xa9PSZrBLc3K8FaYUxrEXVWJeaS1ZDdNzwIRM3DVo42gKqYB20SQ/640?wx_fmt=png&from=appmsg

R中的数据结构

Note
R中有一些术语较为独特,可能会对新用户造成困扰。在R中,对象(object)是指可以赋值给变量的任何事物,包括常量、数据结构、函数,甚至图形。对象都拥有某种模式,描述了此对象是如何存储的,以及某个类(class),像print()这样的泛型函数表明如何处理此对象。 与其他标准统计软件(如SAS、SPSS和Stata)中的数据集类似,数据框dataframe)是R中用于存储数据的一种结构:列表示变量,行表示观测。在同一个数据框中可以存储不同类型(如数值型、字符型)的变量。数据框将是你用来存储数据集的主要数据结构。

向量

向量,vector,就是同一类型的多个元素构成的序列,可以是数值型、字符型、逻辑型等。

创建向量

在R中,最基本的创建向量的方法是使用函数c()

# 创建一个名字是a的向量
a <- c(1, 2, 5, 3, 6, -2, 4)
class(a) # 查看类型
## [1] "numeric"

# 创建一个名字是b的向量
b <- c("one", "two", "three")

# 创建一个名字是d的向量,不用c是为了避免和函数 c() 混淆
d <- c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE)

这里,a是数值型向量,b是字符型向量,而d是逻辑型向量。向量中的值被称为元素(element),比如向量a的第一个元素是1,向量b的第一个元素是"one"

注意,单个向量中的数据有相同的类型或模式(数值型、字符型或逻辑型)。同一向量中无法混杂不同类型的数据。比如:

# 会都变成字符型
a <- c("a",1,TRUE)
a
## [1] "a"    "1"    "TRUE"

除了通过c()创建向量,还可以使用seq()(sequence的缩写)创建数值型的向量,比如,创建一个从1~20的向量,并且步长设置为2:

# 从1到20,中间间隔2
seq(1, 20, 2)
##  [1]  1  3  5  7  9 11 13 15 17 19

重复某个值也可以得到一个向量:

# rep是replicate的缩写
rep(1:2, times = 3) # 重复1 2 三次
## [1] 1 2 1 2 1 2
rep(1:2, each = 3)  # 重复1三次,重复2三次
## [1] 1 1 1 2 2 2

或者最简单的方法,使用数字和冒号,生成连续的数字:

1:5
## [1] 1 2 3 4 5

Tip
标量是只含一个元素的向量,例如f <- 3、g <- “US”和h <- TRUE。它们用于保存常量。

探索向量

查看向量长度:

length(d)
## [1] 6

查看前6行/后6行:

head(seq(1, 20, 2))
## [1]  1  3  5  7  9 11
tail(seq(1, 20, 2))
## [1]  9 11 13 15 17 19

查看唯一元素:

a <- c(1,2,2,3,4,4,4)

# 查看唯一元素
unique(a)
## [1] 1 2 3 4

查看一共有几种不同的元素,以及每个元素的个数,也就是计数:

table(a)
## a
## 1 2 3 4 
## 1 2 1 3

根据位置选择向量元素

通过在方括号中指定元素的位置,我们可以访问(或者叫提取、查看)向量中的某个元素。例如:a[c(2, 4)]用于提取向量a中的第二个和第四个元素。更多示例如下:

# 创建一个向量,取名为a
a <- c(1, 2, 5, 3, 6, -2, 4)

a[3] # 取第3个元素
## [1] 5
a[c(1,3,5)] # 取第1,3,5个元素
## [1] 1 5 6

a[c(1:3)] # 取第1到第3个元素
## [1] 1 2 5
a[c(1, 2, 3)] # 和上面结果相同,也是取第1到第3个元素
## [1] 1 2 5

如果提取不存在的位置,则会返回NA,比如我们提取第10个元素:

a[10]
## [1] NA

NA表示“Not Available”,NA是R语言中一种特殊的类型,常用来表示数据缺失。

如何把提取出来的元素保存为另一个变量呢?比如把a里面的第一个元素保存为变量b?直接赋值即可:

# 提取,赋值,即可
b <- a[1]
b
## [1] 1

替换、删除、增加

如果要替换某个元素,直接提取这个元素并赋予要替换的值即可:

a <- c(1, 2, 5, 3, 6, -2, 4)

# 把向量a的第1个元素换成 m
a[1] <- "m"
a # 注意,此时全部变成字符型了哦!
## [1] "m"  "2"  "5"  "3"  "6"  "-2" "4"

# 同时替换多个元素,注意长度要相同,并且要使用c()放在一个向量中
a[c(1,3,4)] <- c("d","e","f")
a
## [1] "d"  "2"  "e"  "f"  "6"  "-2" "4"

如果要删除某个元素,直接在位置前加负号即可:

a <- c(1, 2, 5, 3, 6, -2, 4)

# 删除a的第一个元素,结果中第一个元素 1 就被删掉了
a[-1]
## [1]  2  5  3  6 -2  4

# 但此时你打印a会发现a还是1, 2, 5, 3, 6, -2, 4,
a
## [1]  1  2  5  3  6 -2  4

# 如果要获得修改后的a,一定要重新赋值!
a <- a[-1]
a # 此时a就是修改后的了
## [1]  2  5  3  6 -2  4

# 同时删除多个元素
a <- c(1, 2, 5, 3, 6, -2, 4)

# 直接把要删除的元素位置放在c()中即可
a[c(-1,-2,-3)]
## [1]  3  6 -2  4

# 如果要获得修改后的a,一定要重新赋值!
a <- a[c(-1,-2,-3)]
a
## [1]  3  6 -2  4

如果要继续增加元素,直接使用c()即可:

# 在向量a中添加3个元素,并赋值给a1
# 注意由于"80", "89", "90"都加了引号,所以修改后的a都变成了字符型
a1 <- c(a, "80", "89", "90")
a1
## [1] "3"  "6"  "-2" "4"  "80" "89" "90"

根据名字选择向量元素

还可以对向量中的每一个元素取一个名字,比如:

# 创建一个命名向量
named_a <- c(age = 18, bmi = 22, weight = 65)
named_a
##    age    bmi weight 
##     18     22     65

此时,向量named_a中的3个元素,都有一个独一无二的名字,此时我们还可以通过向量的名字来访问对应的元素:

named_a["age"]
## age 
##  18

named_a["bmi"]
## bmi 
##  22

查看每个元素的名字(如果这是一个命名向量的话):

names(named_a)
## [1] "age"    "bmi"    "weight"

替换元素的名字:

# 替换第一个元素的名字,从age变为height
names(named_a)[1] <- "height"
named_a
## height    bmi weight 
##     18     22     65

# 同时替换多个元素的名字
names(named_a)[c(1,2)] <- c("height","gg")
#names(named_a)[1:2] <- c("height","gg")
named_a
## height     gg weight 
##     18     22     65

# 同时替换所有元素的名字
names(named_a) <- c("aa","bb","cc")
named_a
## aa bb cc 
## 18 22 65

移除元素的名字:

# 移除元素的名字,注意不能只移除某个元素的名字,要一起移除
names(named_a) <- NULL
named_a
## [1] 18 22 65

根据表达式选择向量元素

除了通过位置和名字选择元素外,还可以通过表达式(也就是TRUE或者FALSE):

a <- c(1,2,3,10,11)

a[a==10] # 选择等于10的元素
## [1] 10
a[a<5]   # 选择小于5的元素
## [1] 1 2 3
a[a %in% c(2,3,11)]  # 选择在(2,3,11)里面的元素,很常用
## [1]  2  3 11

向量排序

如果要对向量排序:

# 创建一个向量a
a <- c(4,1,2,3)
a
## [1] 4 1 2 3

# 排序,默认按照从小到大
sort(a)
## [1] 1 2 3 4

# 按照从大到小的顺序排列
sort(a, decreasing = T)
## [1] 4 3 2 1

# 反转顺序
rev(a)
## [1] 3 2 1 4

order函数返回的是向量元素的一个排列索引,它不是直接对数据进行排序,而是告诉你如何对数据进行排序。

a <- c(4,1,2,3)
a
## [1] 4 1 2 3
order(a)
## [1] 2 3 4 1

order(a)的结果中,第一个数字是2,意思是:原向量a中的第2个元素(也就是1)应该放在第1位,第2个数字是3,意思是:原向量中的第3个元素(也就是2)应该放在第2位…

所以order返回的是原始向量排序后的位置,我们就可以使用这些位置对向量进行排序:

# 默认从小到大
a[order(a)] # 等价于sort(a)
## [1] 1 2 3 4

也可以从大到小:

a[order(a, decreasing = T)]
## [1] 4 3 2 1

去重复

a <- c(1,2,2,3,4,4,4)

# 查看是否有重复
duplicated(a)
## [1] FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE

!表示“非”,也就是反向选择:

!duplicated(a)
## [1]  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE

通过反向选择的方式去重,非常重要的方法:

# 通过反选的方式去重,很重要,!表示反选
a[!duplicated(a)]
## [1] 1 2 3 4

两个向量的操作

取两个向量的交集、并集、差集。

假设有两个向量如下:

a <- c(1,2,3,4)
b <- c(1,2,3,5,6)

取两个向量中共有的元素(交集):

intersect(a,b)
## [1] 1 2 3

取并集:

union(a,b)
## [1] 1 2 3 4 5 6

取向量a有但是b没有的元素(差集):

setdiff(a,b)
## [1] 4

取向量b有但是a没有的元素(差集):

setdiff(b,a)
## [1] 5 6