R编程特性1:向量与向量化

2017 年 11 月 15 日 数萃大数据 louwill

    


    从这一期开始,小编打算从程序语言的角度来认真审视和研究一下R。系列名称就叫做R语言编程特性,从最基本的数据结构开始讲起,包括向量、矩阵、数组、列表、数据框和因子这六大数据类型,R的编程结构和面向对象编程、IO编程、R的性能以及并行计算等内容。

     R虽是统计学家们开发和发展的,但其终究还是一门编程语言。既然是编程语言,那么R就有自身的语法风格和特性。作为R中最基本的数据类型,向量(vector)在R编程架构里占据了最底层也是最核心的位置。并且从广泛意义上的数据类型而言,R中的矩阵和数组甚至是列表都是向量。本文就以向量为主题,探索R向量的循环补齐、索引与取数以及向量化运算等特性。

“一切都是向量”

    在R中一切都是向量,这可能是有点夸张的说法了,但并不妨碍向量成为最基础和最值得我们重视的一种数据结构。对于一切都是向量的说法,我们可以这么理解:R中不存在标量(单个数值),所谓标量是以向量形式存在的,并且R中的矩阵、数组甚至是列表都可以看成是某种意义上的向量。

    标量以向量的形式存在:

  
    
    
    
  1. x <- 1

  2. y <- c(1)

  3. identical(x, y)

  4. [1] TRUE

    矩阵的向量本质:数据虽然以矩阵的形式存在,但本质仍然是向量,只不过是多了行和列这样的属性。

  
    
    
    
  1. z <- matrix(1:6, nrow=3)

  2. z + 3:8

  3.     [,1] [,2]

  4. [1,]    4   10

  5. [2,]    6   12

  6. [3,]    8   14

    在R中,我们可以使用简单的 c()函数来创建一个向量,c 的本意即为concatenate(连接)。下面的代码中小编创建了一个包含五个元素的向量,并将其赋值给变量 x,而 x的本质是一个指针,通过这个指针可以对向量元素进行增删或者更改的操作来进行重赋值。

  
    
    
    
  1. x <- c(18,34,49,52,81)

  2. x

  3. [1] 18 34 49 52 81

    除了 c()函数之外,我们还可以使用 运算符和 seq()函数来创建向量:

  
    
    
    
  1. 1:8

  2. [1] 1 2 3 4 5 6 7 8

 :运算符在for循环中可能会特别好用:

  
    
    
    
  1. for (i in 1:length(x)){}

seq()函通过生成序列来创建向量:

  
    
    
    
  1. seq(10,20,2)

  2. [1] 10 12 14 16 18 20

    和大多数编译语言不同的是,我们在R中创建这个向量并将其赋值给 x的过程中,并不需要对其进行事先声明,这是R和Python等脚本语言的一大特性。

 Matlab:

  
    
    
    
  1. >> syms a,b,x;

  2. >> int(x^2,a,b)

 C:

  
    
    
    
  1. int x;

  2. int y[1]

    由于R没有需要事先声明的限制,在对创建出的向量进行绑定赋值时,其类型是不受限制的。我们可以在将 x绑定到一个数值向量之后,继续再将其绑定到一个字符型向量上去。 这再次提醒我们:变量 x只是一个指针,在不同的时间可以指向不同类型的变量。

  
    
    
    
  1. x <- c(18,34,49,52,81)

  2. x

  3. [1] 18 34 49 52 81

  4. x <- "louwill"

  5. x

  6. [1] "louwill"

向量的循环补齐

    在对两个长度不等的向量执行运算的时候,R会自动对长度较短的向量进行循环补齐,即对长度较短的向量元素进行重复,直至其与要进行运算的另一向量长度相匹配。

  
    
    
    
  1. c(1,3,5) + c(2,4,6,8,10)

  2. [1]  3  7 11  9 13

  3. x <- c(8,2,3,9)

  4. y <- c(2,7)

  5. "*"(x,y)

  6. [1] 16 14  6 63

    下面用矩阵的计算例子来展示向量的循环补齐特性以及印证矩阵的向量本质。

  
    
    
    
  1. x <- matrix(1:8, nrow=2)

  2. x + c(1,2)

  3.     [,1] [,2] [,3] [,4]

  4. [1,]    2    4    6    8

  5. [2,]    4    6    8   10

    在上面的代码中,我们可以看到矩阵的本质其实是一个长向量,将4x2的矩阵看成是一个包含八个元素的长向量,在R中按列存储后就有了矩阵的形态。在执行上述向量加法运算时,R会自动将 c(1,2)进行循环补齐操作,直到将其补成同样是4x2的矩阵为止。

  
    
    
    
  1. c(1,2,3,4,5,6,7,8)

向量索引与访问

    与Python索引从0开始不同的是,R的索引从1开始,当然这并不碍事。R通过 []符号和向量索引来访问向量中的元素:

  
    
    
    
  1. x <- c(rnorm(3),runif(2))

  2. x[c(1,3,5)]

  3. [1]  0.4888147 -1.1989531  0.6171411

  4. x[2:4]

  5. [1]  1.9060878 -1.1989531  0.5635335

  6. y <- 4:5

  7. x[y]

  8. [1] 0.5635335 0.6171411

    也可以用负数下标来删除对应元素:

  
    
    
    
  1. x <- c(2,5,8)

  2. x[-3]

  3. [1] 2 5

  4. x[-1:-2]

  5. [1] 8

向量化运算

    R作为一门像电脑要内存的编程语言,从某种程度上而言是R饱受诟病的原因之一。因此坊间有个约定就是尽量少在R中使用循环,尤其是在数据量较大的情形下,据说效率的低下程度令人发指。改变并提升代码效率的有效途径便是向量化(vectorize),即将运算符或者函数作用在向量的每一个元素上的一种理念。

向量化运算符

  
    
    
    
  1. x <- c(2,6,0)

  2. y <- c(1,5,8)

  3. x > y

  4. [1]  TRUE  TRUE FALSE

  5. z <- rnorm(5)

  6. round(z)

  7. [1]  0 -1  1  0  3

    上面的代码例子是以向量形式作为结果输出的,下面再看一例运用向量化运算符并以矩阵形式输出结果:

  
    
    
    
  1. xy <- function(x) return(c(x, x^2))

  2. sapply(-3:3, xy)

  3.     [,1] [,2] [,3] [,4] [,5] [,6] [,7]

  4. [1,]   -3   -2   -1    0    1    2    3

  5. [2,]    9    4    1    0    1    4    9

    向量化函数 在R中执行向量化运算的核心函数就是apply函数族,其中包括以 apply()函数为基础,以 lapply()sapply()为核心函数的等8个向量化计算函数,运算例子如下:

  
    
    
    
  1. e <- list(alpha=3:7,beta=exp(2:8),gamma=c(TRUE,FALSE,FALSE,TRUE))

  2. lapply(e, fivenum)  

  3. $alpha

  4. [1] 3 4 5 6 7

  5. $beta

  6. [1]    7.389056   37.341843  148.413159  750.030976 2980.957987

  7. $gamma

  8. [1] 0.0 0.0 0.5 1.0 1.0

  9. sapply(e, fivenum,simplify=TRUE)

  10.     alpha        beta gamma

  11. [1,]     3    7.389056   0.0

  12. [2,]     4   37.341843   0.0

  13. [3,]     5  148.413159   0.5

  14. [4,]     6  750.030976   1.0

  15. [5,]     7 2980.957987   1.0

具体函数用法含义和区别可参见

R语言向量化运算:apply函数族用法心得



参考资料:

R语言编程艺术



欢迎大家关注微信公众号:数萃大数据



课程公告

深度学习培训班【上海站】

时间:2017年12月23-24日

地点:上海创梦云实训创新中心

更多详情,请扫描下面二维码




登录查看更多
0

相关内容

【干货书】R语言书: 编程和统计的第一课程,
专知会员服务
111+阅读 · 2020年5月9日
【2020新书】C++20 特性 第二版,A Problem-Solution Approach
专知会员服务
58+阅读 · 2020年4月26日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
【新书】Python数据科学食谱(Python Data Science Cookbook)
专知会员服务
114+阅读 · 2020年1月1日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
87+阅读 · 2019年11月25日
100行Python代码,轻松搞定神经网络
大数据文摘
4+阅读 · 2019年5月2日
百闻不如一码!手把手教你用Python搭一个Transformer
大数据文摘
18+阅读 · 2019年4月22日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
【干货】​深度学习中的线性代数
专知
21+阅读 · 2018年3月30日
为什么你应该学 Python ?
计算机与网络安全
4+阅读 · 2018年3月24日
机器之心最干的文章:机器学习中的矩阵、向量求导
深度学习世界
12+阅读 · 2018年2月7日
机器学习(19)之支持向量回归机
机器学习算法与Python学习
12+阅读 · 2017年10月3日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
python pandas 数据处理
Python技术博文
4+阅读 · 2017年8月30日
Question Generation by Transformers
Arxiv
5+阅读 · 2019年9月14日
Universal Transformers
Arxiv
5+阅读 · 2019年3月5日
Arxiv
10+阅读 · 2018年4月19日
Arxiv
6+阅读 · 2018年3月28日
Arxiv
7+阅读 · 2018年1月10日
VIP会员
相关资讯
100行Python代码,轻松搞定神经网络
大数据文摘
4+阅读 · 2019年5月2日
百闻不如一码!手把手教你用Python搭一个Transformer
大数据文摘
18+阅读 · 2019年4月22日
Python3.8新特性概览
Python程序员
4+阅读 · 2018年12月8日
【干货】​深度学习中的线性代数
专知
21+阅读 · 2018年3月30日
为什么你应该学 Python ?
计算机与网络安全
4+阅读 · 2018年3月24日
机器之心最干的文章:机器学习中的矩阵、向量求导
深度学习世界
12+阅读 · 2018年2月7日
机器学习(19)之支持向量回归机
机器学习算法与Python学习
12+阅读 · 2017年10月3日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
python pandas 数据处理
Python技术博文
4+阅读 · 2017年8月30日
Top
微信扫码咨询专知VIP会员