本讲简要介绍R中常见的数据结构,重在梳理,不求详尽,部分内容改编自Hadley Wickham的《Advanced R》一书。
欢迎转载,但请注明出处!
数据结构
当你在使用电脑时,各种五光十色的界面、操作、交互等等,究其本质来说,无非是一个你给电脑
数据
和
指令
,电脑进行处理,再返回给你新数据的过程,而程序语言就类似你和电脑沟通的媒介,毕竟电脑不通人言啊!
说到各式各样的数据交互,通常量还蛮大,我们怎能忍心duang的一下,直接一股脑抛给电脑兄: “处理去吧!”,脑: “WTF?”,因为原本很多数据彼此之间预先存在联系、又或在接下来的处理过程中也是难解难分,所以为了
方便电脑读取和处理数据
,我们得用一些人为的方法将数据
合理而高效
的安排及存放在电脑中,这就是数据结构的由来及含义。
数据结构不仅包含数据本身,还包括它们的内在关系,以及一系列操作处理数据的规范。
对于绝大多数高级编程语言,我们无需担心要自己弄数据结构,这些都必然是内置好的了。那么,在R中,我们主要使用的是哪些数据结构呢?
|
元素种类相同
|
元素种类不同
|
一维
|
Atomic vector (原子向量)
|
Recursive vector = List (递归向量 = 列表)
|
二维
|
Matrix (矩阵)
|
Data frame (数据集)
|
多维
|
Array (数组)
|
|
从上表我们可以看出,一维的两种向量结构向二维及多维拓展,进而形成了R的其他主要数据结构,向量之于R类似于基石之于广厦!
向量 (vector):R之魂
我们最初接触这个概念,大都是在中学学习数学的时候,对于既有大小又有方向的量,我们称之向量,在坐标系中它意味的是一个点相对于另一个点的距离和方位,形象的表示为一个箭头。在n维坐标系中,一个点距离原点的向量就表示为
(X1, X2, ... , Xn)
。
而在程序语言中,向量最初只是用来描述装了一串数字的载体,比如
(1, 2, 3, 4, 5)
就是一个五维向量,装了1-5这五个数字,这和数学坐标系中的定义是一致的,而如今,其含义已经大为拓展,不再只是装数字,可以装anything!
当向量其中包含的元素类型为同一种基本类型 (逻辑,整型,浮点,字符等) 时,称其为原子向量;而类型不一致时,则称为递归向量,俗称列表 (List)。
所谓
原子
,指的是向量中每个元素不可再分割成sub-vector,是最小实体;而list中的元素还可以是atomic vector或者list,甚至array和data frame,它们可以继续包含多个内部元素,一直循环下去,这种行为也就是
递归
的本义。
dbl.atom 1, 2, 3) int.atom 1L, 2L, 3L) typeof(dbl.atom)
## [1] "double"
typeof(int.atom)
## [1] "integer"
alist 1:9, c("I", "LOVE", "U"), c(TRUE, FALSE), c(1.2, 3.4, 5.6))
str(alist)
## List of 4
## $ : int [1:9] 1 2 3 4 5 6 7 8 9
## $ : chr [1:3] "I" "LOVE" "U"
## $ : logi [1:2] TRUE FALSE
## $ : num [1:3] 1.2 3.4 5.6
向量作为一个
装载容器
,它是
动态
的,即容量可变,可以随时插入或删除其中的元素;同时,它也是
有序
的,即其中的元素是有序号 (index)的。
R向量的三个特性
dbl.atom == int.atom
## [1] TRUE TRUE TRUE
"=="(dbl.atom, int.atom)
## [1] TRUE TRUE TRUE
identical(dbl.atom, int.atom)
## [1] FALSE
注意:有朋友可能会联想到著名的apply家族函数,它们可以让代码更简洁和紧凑,可其实背后执行的是
R循环
,所以效率方面并未有太大提升。然而大多数时候,简洁易懂的代码更有意义!详情请深入了解
Tidyverse R包集合
的
思想
。
c(1
, 2) + c(3, 4, 5, 6, 7)
## Warning in c(1, 2) + c(3, 4, 5, 6, 7): longer object length is not a
## multiple of shorter object length
## [1] 4 6 6 8 8
1 + 1:9
## [1] 2 3 4 5 6 7 8 9 10
emotion "LOVE", "HATE")
my.emo.2u "I"]
my.emo.2u
## [1] "LOVE"
因为其他主要数据结构也是来自于向量的拓展,所以上面三个特性基本普适!
矩阵和数组
没多少可讲的,概念比较简单,就是在原子向量的基础上加上了维度 (dim) 这个属性,
有行,有列,有维,就在这晒,晒足180天
。
my.matrix 1:9, nrow = 3)
my.matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
dim(my.matrix)
## [1] 3 3
my.array 1:12, c(2, 3, 2)) my.array
## , , 1
##
## [,1] [,2] [,3]
## [1,] 1 3 5
## [2,] 2 4 6
##
## , , 2
##
## [,1] [,2] [,3]
## [1,] 7 9 11
## [2,] 8 10 12
dim(my.array)
## [1] 2 3 2
数据集
初看起来,数据集很像矩阵,一般都是有行和列两个维度,然而,数据集是异质性的,即其中的数值并不需要都是同一种类型,故而其本质上更像一个列表,
每一列就是列表中的一个元素
,唯独的一点限制,就是每个元素
长度得相同
。
xiaochou "一", "杯", "敬", "明", "天"), y = c("一", "杯", "敬", "过", "往"))
xiaochou
## x y
## 1 一 一
## 2 杯 杯
## 3 敬 敬
## 4 明 过
## 5 天 往
str(xiaochou)
## 'data.frame': 5 obs. of 2 variables:
## $ x: Factor w/ 5 levels "杯","敬","明",..: 5 1 2 3 4
## $ y: Factor w/ 5 levels "杯","过","敬",..: 5 1 3 2 4
因子 (Factor)
最后,还要提一位重要的小朋友——因子,它从本质上来说是整数型 (integer) 原子向量,额外多了两个属性:类属性
factor
以及
levels
属性,后者用来定义向量中预先设定好的的值,换言之,因子是专门用来存放离散数据 (分类数据) 的,这在数据集的处理过程中有重要意义,以后会详解。
x 3, 4, 4, 3))
x
## [1] 3 4 4 3
## Levels: 3 4
class(x)
## [1] "factor"
levels(x)
## [1] "3" "4"
as.double(x)
## [1] 1 2 2 1
结语
一切皆对象,运行靠向量!
阅读
蓝色链接
内容请点击
阅读原文
!
阅读
蓝色链接
内容请点击
阅读原文
!
阅读
蓝色链接
内容请点击
阅读原文
!