R语言编程技术(2)


  上节简单的介绍了 R 语言的三种特性,这节讨论编程技术的核心技术 数据结构 ,不要被吓到了。(这个逼装灰常好, 哈哈)

  一提到数据结构,第一印象多半是大学时代折磨人的课程,事实上 R 语言内置的数据结构是被底层语言封装过的,所以没有复杂的指针指向指的你发晕,也不会一不小心造成了内存泄漏,这就是使用高级语言的好处,但是也注定了调包侠的命运,知其然而不知所以然(悲哀!呜呜~)

   R 内置了五种最基本的数据结构:向量,列表,矩阵,数据框,多维数组,见下表:

数据结构名创建函数类型特性类比底层数据结构
向量c一维同类型数据, 最基本结构动态数组
列表list一维S3对象基本结构, 灵活多变多叉树
矩阵matrix二维同数据类型, 运算快二维动态数组
数据框data.frame二维存储不同类型数据, 标准数据表多叉树
多维数组array可多维高维度多维动态数组


  这里我觉得列表和数据框应该是多叉树,也许是哈希,欢迎拍砖指正,这里特别说明一下列表和数据框,数据框应该属于列表的一个特例,列表的当中第一层元素就相当于数据框的列,用代码说话:

# 创建一个列表
l <- list(1,2,3)
# [[1]]
# [1] 1
#
# [[2]]
# [1] 2
#
# [[3]]
# [1] 3
# 创建数据框
df <- data.frame(1, 2, 3)
#   X1 X2 X3
# 1  1  2  3
# 检查类型
typeof(l)
# [1] "list"
typeof(df)
# [1] "list"


  检查类型是发现 list data.frame 都是 list ,没错这就是真相,S3对象都是由list构造的,内置的data.frame是S3对象,因此它的本质就是一个list,只是给了它取了一个类名叫data.frame。不信?代码为证。

# 查看函数data.frame代码
data.frame
# .......
# return(structure(list(), names = character(), row.names # = row.names, class = "data.frame"))


  这句函数返回语句充分说明了问题,构建了一个名为data.frame的对象,若不太清楚 R 对象 S3对象系统,可以阅读一下 R神 AdvanceR ,许多博客和参考资料都有很详细的讲解,我这里就不多废话了。

  最后还是要强调一下明白这些有什么卵用,毕竟这才是使用者比较关心的,但是我说的是,你要做一辈子的调包侠,还是博古通今? (这个逼装的,我给自己满分)

  事实上在做数据处理工作时,基本上就是在对数据进行压缩,扩展,映射,转化,而完成这些工作的最基本就是在进行数据结构的变换,又到代码说话时刻:

# 以iris数据集为例, 这里借用一下R神的dplyr包来说明问题
library(dplyr)
iris %>% as.tbl()
# A tibble: 150 x 5
# Groups:   Species [3]
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#          <dbl>       <dbl>        <dbl>       <dbl>  # <fctr>
#  1          5.1         3.5          1.4         0.2  setosa
#  2          4.9         3.0          1.4         0.2  setosa
#  3          4.7         3.2          1.3         0.2  setosa
#  4          4.6         3.1          1.5         0.2  setosa
#  5          5.0         3.6          1.4         0.2  setosa
#  6          5.4         3.9          1.7         0.4  setosa
#  7          4.6         3.4          1.4         0.3  setosa
#  8          5.0         3.4          1.5         0.2  setosa
#  9          4.4         2.9          1.4         0.2  setosa
# 10          4.9         3.1          1.5         0.1  setosa
# ... with 140 more rows


  这里为了方便观察数据, 用dplyr包来说明问题,可以直观的观察到数据结构的变化(因为屏幕大小有限)

# 分类计数
iris %>% as.tbl() %>% group_by(Species) %>% count()
# A tibble: 3 x 2
# Groups:   Species [3]
#     Species     n
#      <fctr> <int>
# 1     setosa    50
# 2 versicolor    50
# 3  virginica    50


  不就是个分类汇总吗,有啥了不起的,我要说明的不是分类汇总这个操作,而是数据结构的变化,数据由原始的 150 × 5 被映射成了 3 × 2,数据类型也发生了变化,这里每个分类组的数据通过 count 函数被映射成单值,最终组成了一个新的数据框,但是这里数据结构没有发生变化。

iris %>% as.tbl() %>% class()
# [1] "tbl_df"     "tbl"        "data.frame"
iris %>% as.tbl() %>% typeof()
# [1] "list"
iris %>% as.tbl() %>% group_by(Species) %>% count() %>% typeof()
# [1] "list"


  注意: as.tbl 函数操作只是给原生态的 data.frame 添加了新的类,扩充了一下它的功能,能更好的兼容使用dplyr包当中的函数,数据结构的本质上它还是一个 list


  最后再举一个数据结构发生变化的例子:

iris %>% as.tbl() %>% length()
# [1] 5


  list 通过 length 函数被映射成了一个向量, 这里我们理解函数就等价于某种算法, 算法作用在数据结构上,得到了新的数据结构,代码的工作就是在做这样的事情,因此掌握数据结构对编程技术来说显得非常重要,因为你的任何需求都基本包含在这个套路当中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值