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

浏览: 1954

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

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

“一切都是向量”

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

    标量以向量的形式存在:

 x <- 1
y <- c(1)
identical(x, y)
[1] TRUE

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

 z <- matrix(1:6, nrow=3)
z + 3:8
    [,1] [,2]
[1,]    4   10
[2,]    6   12
[3,]    8   14

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

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

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

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

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

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

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

seq(10,20,2)
[1] 10 12 14 16 18 20

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

 Matlab:

>> syms a,b,x;
>> int(x^2,a,b)

 C:

int x;
int y[1]

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

x <- c(18,34,49,52,81)
x
[1] 18 34 49 52 81
x <- "louwill"
x
[1] "louwill"

向量的循环补齐

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

c(1,3,5) + c(2,4,6,8,10)
[1]  3  7 11  9 13
x <- c(8,2,3,9)
y <- c(2,7)
"*"(x,y)
[1] 16 14  6 63

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

x <- matrix(1:8, nrow=2)
x + c(1,2)
    [,1] [,2] [,3] [,4]
[1,]    2    4    6    8
[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通过 []符号和向量索引来访问向量中的元素:

x <- c(rnorm(3),runif(2))
x[c(1,3,5)]
[1]  0.4888147 -1.1989531  0.6171411
x[2:4]
[1]  1.9060878 -1.1989531  0.5635335
y <- 4:5
x[y]
[1] 0.5635335 0.6171411

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

x <- c(2,5,8)
x[-3]
[1] 2 5
x[-1:-2]
[1] 8

向量化运算

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

向量化运算符

x <- c(2,6,0)
y <- c(1,5,8)
x > y
[1]  TRUE  TRUE FALSE
z <- rnorm(5)
round(z)
[1]  0 -1  1  0  3

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

xy <- function(x) return(c(x, x^2))
sapply(-3:3, xy)
    [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]   -3   -2   -1    0    1    2    3
[2,]    9    4    1    0    1    4    9

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

e <- list(alpha=3:7,beta=exp(2:8),gamma=c(TRUE,FALSE,FALSE,TRUE)) 
lapply(e, fivenum)  
$alpha
[1] 3 4 5 6 7

$beta
[1]    7.389056   37.341843  148.413159  750.030976 2980.957987

$gamma
[1] 0.0 0.0 0.5 1.0 1.0

sapply(e, fivenum,simplify=TRUE)
    alpha        beta gamma
[1,]     3    7.389056   0.0
[2,]     4   37.341843   0.0
[3,]     5  148.413159   0.5
[4,]     6  750.030976   1.0
[5,]     7 2980.957987   1.0

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

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


往期精彩:

R语言爬虫系列6|动态数据抓取范例

R语言爬虫系列5|正则表达式与字符串处理函数

R语言爬虫系列4|AJAX与动态网页介绍

R语言爬虫系列3|HTTP协议

R语言爬虫系列2|XML&XPath表达式与R爬虫应用

R语言爬虫系列1|HTML基础与R语言解析

如何写出整洁规范的R代码?是时候讨论一下代码规范性了

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

Python面向对象编程:数据封装、继承和多态

[译]为什么R语言是当今最值得学习的数据科学语言

image.png

推荐 0
本文由 鲁伟 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册