R 数据结构(Data Structures) 简介8

目录

一些定义

1. 向量(Vectors)

2. 矩阵(Matrices)

3. 数组(Arrays)

4. 数据框(Data frames)

1. attach(), detach() 和 with()

2. 实例标识符(Case Identifiers)


R拥有许多用于存储数据的对象(objects)类型,包括标量(scalars), 向量(vectors), 矩阵(matrices), 数组(arrays), 数据框(data frames) 和列表(lists). 它们存在存储数据的类型、创建方式、结构复杂度,以及用于定位和访问其中个别元素的标记等方面均有所不同。下图给出了这些数据结构的一个示意图:

R 中的数据结构

让我们从向量开始,逐个探究每一种数据结构。

一些定义

R 中有一些术语较为独特,可能会对用户造成困扰。

在 R 中,对象(object) 是指可以赋值给变量(variable) 的任何事物,包括常量、数据结构、函数,甚至图形。对象都拥有某种模式(mode), 模式描述了此对象是如何存储的;以及某个类(class), 指示像 print 这样的泛型函数(generic functions) 如何处理此对象。

与其他标准统计软件(如 SAS, SPSS 和 Stata)中的数据集类似,数据框(data frame) 是 R 中用于存储数据的一种结构:列表示变量(variables), 行表示观测(observations). 在同一个数据框中可以存储不同类型(如数值型 numeric 或字符型 character)的变量。数据框将是你用来存储数据集的主要数据结构。

因子(factors) 是名义型变量或有序型变量。它们在 R 中被特殊地存储和处理,之后的博文中会详细介绍因子的处理。

其他多数术语你应该比较熟悉了,它们基本都遵循统计和计算中术语的定义。

1. 向量(Vectors)

向量(Vectors) 是用于存储数值型(numeric), 字符型(character) 或逻辑型(logical) 数据的一维数组。执行组合功能函数(combine function) c() 可用来创建向量。各类向量如下例所示:

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

这里,a 是数值型向量,b 是字符型向量,而 c 是逻辑型向量。注意,单个向量中的数据必须拥有相同的类型或模式 mode(数值型 numeric, 字符型 character, or 逻辑型 logical). 同一向量中无法混杂不同模式的数据。


注意:标量(Scalars) 是只含一个元素的向量,例如

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

它们用于保存常量。


通过在方括号中给定元素所处位置的数值,我们可以访问向量中的元素。例如,a[c(2,4)] 用于访问向量 a 中的第二个和第四个元素:

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

更多示例如下:

> a<-c("k","j","h","a","c","m")
> a[3]
[1] "h"
> 
> a[c(1,3,5)]
[1] "k" "h" "c"
> 
> a[2:6]  
[1] "j" "h" "a" "c" "m"

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

> a<-c(2:6)
> a
[1] 2 3 4 5 6
> 
> a<-c(2,3,4,5,6)
> a
[1] 2 3 4 5 6

2. 矩阵(Matrices)

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

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

其中 vector 包含了矩阵的元素,nrow 和 ncol 用以指定行和列的维数,dimnames 包含了可选的、以字符型向量表示的行名和列名。 选项 byrow 则表明矩阵应当按行填充(byrow=TRUE) 还是按列填充(byrow=FALSE), 默认情况下按列填充。代码清单 2-1 中的代码演示了 matrix() 函数的用法。

> #-------------------------------------------------------------------------
> # 代码清单2-1 创建矩阵
> #-------------------------------------------------------------------------
> y<-matrix(1:20,nrow=5,ncol=4) # 1. 创建一个5*4的矩阵
> 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,68)    
> rnames<-c("R1", "R2")
> cnames<-c("C1", "C2")                      
> 
> mymatrix<-matrix(cells,nrow=2,ncol=2,byrow=TRUE, # 2. 按行填充的2*2矩阵
+                  dimnames=list(rnames,cnames))
> mymatrix
   C1 C2
R1  1 26
R2 24 68
> 
> mymatrix<-matrix(cells,nrow=2,ncol=2,byrow=FALSE, # 3. 按列填充的2*2矩阵
+                  dimnames=list(rnames,cnames))    
> mymatrix                               
   C1 C2
R1  1 24
R2 26 68
> #-------------------------------------------------------------------------
  1. 我们首先创建了一个 5\times4 的矩阵;
  2. 接着创建了一个 2\times 2 的含行、列名标签的矩阵,并按进行填充;
  3. 接着创建了一个 2\times 2 的含行、列名标签的矩阵,并按进行填充;

我们可以使用下标和方括号来选择矩阵中的行、列或元素。 x[1,] 指矩阵 x 中的第 i 行,x[,j] 指第 j 列,x[i,j] 指第 i 行第 j 个元素。选择多行或多列时,下标 i 和 j 可为数值型向量,如代码清单 2-2 所示:

> #----------------------------------------------------------------------------------------
> # 代码清单2-2 矩阵下标的使用
> #----------------------------------------------------------------------------------------
> x<-matrix(1:10,nrow=2) # 创建一个内容为数字1到10的2*5矩阵,默认情况下,矩阵按列填充
> x
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    3    5    7    9
[2,]    2    4    6    8   10
> x[2,] # 选择第2行的元素                                       
[1]  2  4  6  8 10
> x[,2] # 选择第2列的元素                                         
[1] 3 4
> x[1,4] # 选择第1行第4列的元素                                        
[1] 7
> x[1,c(4,5)] # 选择第1行第4、5列的元素                                  
[1] 7 9
> #----------------------------------------------------------------------------------------

矩阵都是二维的,和向量类似,矩阵中也仅能包含一种数据类型。当维度超过 2 时,不妨使用数组(arrays). 当有多种模式的数据时,可以使用数据框(data frames).

3. 数组(Arrays)

数组(arrays) 与矩阵类似,但是数组的维度可以大于 2. 数组可通过 array 函数创建,形式如下:

myarray <- array(vector, dimensions, dimnames)

其中 vector 包含了数组中的数据,dimensions 是一个数值型向量,给出了各个维度下标的最大值,而 dimnames 是可选的(optional)、各维度名称标签的列表。代码清单 2-3 给出了一个创建三维( 2\times 3\times 4 ) 数值型数组的示例。

> #----------------------------------------------------------
> # 代码清单2-3 创建一个数组
> #----------------------------------------------------------
> 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

> #----------------------------------------------------------

4. 数据框(Data frames)

由于不同的列可以包含不同模式(数值型、字符型等)的数据,数据框(Data frames) 比矩阵更为常见。它与你通常在 SAS, SPSS 和 Stata 中看到的数据集类似。数据框将是你在 R 中最常处理的数据结构。

之前介绍过的 mpg 数据集包含了数值型和字符型数据。由于数据有多种模式,无法将此数据集放入一个矩阵。在这种情况下,使用数据框是最佳选择。

> library(tidyverse)
> library(ggplot2)
> dim(mpg)
[1] 234  11
> mpg[1:10,]
# A tibble: 10 x 11
   manufacturer model      displ  year   cyl trans      drv     cty   hwy fl    class  
   <chr>        <chr>      <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr>  
 1 audi         a4           1.8  1999     4 auto(l5)   f        18    29 p     compact
 2 audi         a4           1.8  1999     4 manual(m5) f        21    29 p     compact
 3 audi         a4           2    2008     4 manual(m6) f        20    31 p     compact
 4 audi         a4           2    2008     4 auto(av)   f        21    30 p     compact
 5 audi         a4           2.8  1999     6 auto(l5)   f        16    26 p     compact
 6 audi         a4           2.8  1999     6 manual(m5) f        18    26 p     compact
 7 audi         a4           3.1  2008     6 auto(av)   f        18    27 p     compact
 8 audi         a4 quattro   1.8  1999     4 manual(m5) 4        18    26 p     compact
 9 audi         a4 quattro   1.8  1999     4 auto(l5)   4        16    25 p     compact
10 audi         a4 quattro   2    2008     4 manual(m6) 4        20    28 p     compact

数据框可通过函数 data.frame() 创建:

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

其中列向量 col1, col2, col3 等可为任何类型(如字符型、数值型或逻辑型)。每一列的名称可由函数 names 指定。代码清单 2-4 清晰地展示了相应用法。

> #----------------------------------------------------------
> # 代码清单2-4 创建一个数据框
> #----------------------------------------------------------
> patientID<-c(1,2,3,4)
> age<-c(25,34,28,52)
> diabetes<-c("Type1","Type2","Type1","Type1")
> status<-c("Poor","Improved","Excellent","Poor")
> patientdata<-data.frame(patientID,age,diabetes,status)
> patientdata
  patientID age diabetes    status
1         1  25    Type1      Poor
2         2  34    Type2  Improved
3         3  28    Type1 Excellent
4         4  52    Type1      Poor
> #----------------------------------------------------------

每一列数据的模式必须唯一,不过你却可以将多个模式的不同列放到一起组成数据框。由于数据框与分析人员通常设想的数据集的形态较为接近,我们在讨论数据框时将交替使用术语列(columns)变量(variables).

选取数据框中元素的方式有若干种。你可以使用前述(如矩阵中的)下标记号,亦可直接指定列名。代码清单 2-5 使用之前创建的 patientdata 数据框演示了这些方式。

> #----------------------------------------------------------
> # 代码清单2-5 选取数据框中的元素
> #----------------------------------------------------------
> patientdata[1:2]
  patientID age
1         1  25
2         2  34
3         3  28
4         4  52
> patientdata[c("diabetes","status")]
  diabetes    status
1    Type1      Poor
2    Type2  Improved
3    Type1 Excellent
4    Type1      Poor
> patientdata$age # 表示 patientdata 数据框中的变量 age
[1] 25 34 28 52
> #----------------------------------------------------------

patientdata$age 中的记号 $ 是新出现的。它被用来选取一个给定数据框中的某个特定变量。例如,如果你想生成糖尿病类型变量 diabetes 和病情变量 status 的列联表(cross-tabulate diabetes type by status),使用以下代码即可:

> table(patientdata$diabetes, patientdata$status)
       
        Excellent Improved Poor
  Type1         1        0    2
  Type2         0        1    0

在每个变量名前都键入一次 patientdata$ 可能会让人生厌,所以不妨走一些捷径。可以联合使用函数 attach() 和 detach() 或者单独使用函数 with() 来简化代码。

1. attach(), detach() 和 with()

函数 attach() 可将数据框添加到 R 的搜索路径中。R 在遇到一个变量名以后,将检查搜索路径中的数据框。以 R 的内置的汽车数据 mtcars(和之前分析过的名为 mpg 的数据集不同,在 mtcars 数据集中 mpg 是一个变量)为例,可以使用以下代码获取英里 / 加仑,即每加仑燃料所行英里数(mpg) 变量的描述性统计量,并分别绘制此变量与发动机排量(disp) 和车身重量(wt) 的散点图:

summary(mtcars$mpg)
plot(mtcars$mpg, mtcars$disp)
plot(mtcars$mpg, mtcars$wt)

# 以上代码也可写成
attach(mtcars)
  summary(mpg)
  plot(mpg, disp)
  plot(mpg, wt)
detach(mtcars)

函数 detach() 将数据框从搜索路径中移除。值得注意的是,detach() 并不会对数据框本身做任何处理。这句是可以省略的,但它其实应当被例行地放入代码中,因为这是一个好的编程习惯。

当名称相同的对象不止一个时,这种方法的局限性就很明显了。考虑以下代码:

> mpg<-c(25,36,47)
> attach(mtcars)
The following object is masked _by_ .GlobalEnv:

    mpg

> plot(mpg,wt)
Error in xy.coords(x, y, xlabel, ylabel, log) : 
  'x' and 'y' lengths differ
> mpg
[1] 25 36 47

这里,在数据框 mtcars 被绑定(attach) 之前,你们的环境中已经有了一个名为 mpg 的对象。在这种情况下,原始对象将取得优先权,这与你们想要的结果有所出入。由于 mpg 中有 3 个元素而 disp 中有 32 个元素,

> dim(mtcars)
[1] 32 11
> mtcars$disp
 [1] 160.0 160.0 108.0 258.0 360.0 225.0 360.0 146.7 140.8 167.6 167.6 275.8
[13] 275.8 275.8 472.0 460.0 440.0  78.7  75.7  71.1 120.1 318.0 304.0 350.0
[25] 400.0  79.0 120.3  95.1 351.0 145.0 301.0 121.0

故 plot 语句出错。函数 attach() 和 detach() 最好在你分析一个单独的数据框,并且不太可能有多个同名对象时使用。任何情况下,都要当心那些告知某个对象已被屏蔽(masked) 的警告。

除此之外,另一种方式是使用函数 with(). 可以这样重写上例:

with(mtcars,{
  print(summary(mpg))
  plot(mpg,disp)
  plot(mpg,wt)
})

在这种情况下,花括号{ } 之间的语句都针对数据框 mtcars 执行,这样就无须担心名称冲突了。如果仅有一条语句(例如 summary(mpg)),那么花括号{ } 可以省略。

函数 with() 的局限性在于,赋值仅在此函数的括号内生效。考虑以下代码:

> with(mtcars,{
+    stats <- summary(mpg)
+    stats
+   })
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 
> stats
错误: 找不到对象'stats'

如果你需要创建在 with() 结构以外存在的对象,使用特殊赋值符 <<- 替代标准赋值符(<-) 即可,它可将对象保存到 with() 之外的全局环境中。这一点可通过以下代码阐明:

> with(mtcars,{
+    nokeepstats<-summary(mpg)
+    keepstats<<-summary(mpg)
+ })
> nokeepstats
错误: 找不到对象'nokeepstats'
> keepstats
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  10.40   15.43   19.20   20.09   22.80   33.90 

相对于 attach(), 多数的 R 书籍更推荐使用 with(). 个人认为从根本上说,选择哪一个是自己的偏好问题,并且应当根据你的目的和这两个函数含义的理解而定。我们会交替使用这两个函数。

2. 实例标识符(Case Identifiers)

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

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

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

将 patientID 指定为 R 中标记各类打印输出和图形中实例名称所用的变量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Rust数据结构是指在Rust编程语言中可以用于存储和组织数据的不同方式和类型。Rust提供了许多内置的数据结构,同时也可以使用各种第三方库来扩展这些数据结构。 常见的Rust数据结构包括: 1. 向量(Vectors):向量是一个动态长度的数组,可以在其中存储任意类型的数据。向量可以动态增长或缩小,也可以按索引访问元素。 2. 哈希映射(Hash Maps):哈希映射是一种键值对的数据结构,其中每个键都与一个唯一的值相关联。哈希映射的插入和查找操作的时间复杂度通常为O(1),因此在需要快速查找或数据去重的场景中非常有用。 3. 字符串(Strings):Rust中的字符串是一系列Unicode标量值的集合。它们可以通过字面量、转换或动态构建来创建和操作。Rust还提供了许多与字符串相关的方法和操作符。 4. 切片(Slices):切片是对数组或向量的引用,允许您引用整个集合或仅引用集合的一部分。切片非常适用于通过传递指定范围的数据来减少内存占用和提高性能的情况。 此外,还有很多其他数据结构可以在Rust中使用,例如堆栈、队列、链表等。Rust还提供了许多强大的工具和概念,如所有权、借用和生命周期,这些可以帮助开发人员安全地管理数据结构的访问和修改。 通过使用各种数据结构,Rust为开发人员提供了灵活和高效的方式来存储和操作数据,使他们能够更轻松地构建稳健和高性能的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙珩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值