【上一篇:73.关于向量基础知识】
【下一篇:75.关于原子向量类型的强制转换和向量元素的命名】
R中没有标量的说法:当将一个数字或一个字符串赋给一个对象,这个对象并不是一个变量,而是一个长度为1的向量。
> (a <- 1)
> [1] 1
向量的类型
logical,integer,double,character是四种最重要的atomic vector类型,raw和complex在数据分析中很少用到。
1)logical vectors是最简单的向量类型,因为它只有三个值:TRUE,FALSE,NA。逻辑向量一般由比较运算产生。
2)integer vectors和double vectors统称为numeric vectors。R中的数字默认都是double类型,在数字后放一个“L”表示是integer类型。
3)character vectors是最复杂的向量类型,因为字符向量中每个元素都是一个string,而每个字符串可以包含任意数量的数据。
R中,integer和double的不同不是特别重要,但有两点不同需要注意:1)double(双精度)是近似的,因为double表示的浮点数并不能总是用固定数量的内存精确表示,所以sqrt(2)^2并不等于2,两者相减得到一个很小的差值。所以,在对浮点数进行 == 比较的时候要谨慎些,可以用dplyr::near(x,y,tol = .Machine$double.eps^0.5)函数设置比较时的容错。2)integer有一个特殊值:NA,double有四个特殊值:NA,NaN(Not a Number),Inf和-Inf。后三个在除法运算中会出现,c(-1,0,1)/0 得到-Inf,NaN,Inf。判断是否是特殊值的函数有is.finite()、is.infinite()、is.na()、is.nan()。
关于character vectors,需要提到一个底层字符串实现的重要特性:R使用全局字符串池,也就是说每个唯一字符串仅在内存中存储一次,字符串的每次使用均指向那个表示(也就是使用的时候只存一个指针就好,一个指针只占8个bytes)。这样可以节省冗余字符串的内存。用pryr::object_size()函数可以查看对象占用内存大小:比如c("a")对象大小是112 bytes,rep("a",100)的大小是904 bytes,计算方法为:904=112 + 8 *(100-1),这里的8是指针的大小。
typeof()函数用来判断对象的类型,mode()函数也可以。两者的关系是mode()函数是基于typeof()的。两者的区别是,mode()函数除了可以获得对象的类型,还可以设置对象的类型;typeof()可以区分integer和double,mode()则会统一返回numeric。
向量的长度
前面说过,向量的长度(也就是向量中元素的个数)可以用length()函数得到,也提到了R中并不存在标量这一说,当你看到向量时一个数字的时候,要自动将其转换成一个长度为1的向量。
问题在于:两个不同长度的向量之间可以进行数学运算或比较运算吗?答案是:当然可以。在做长度不同的两个向量之间的运算时,R隐式地将较短的向量通过repeat、recyle扩展到与较长向量相同的长度,这叫做vector recycling。
R中大部分内置函数是vectorised的,也就是说当参与计算的两个或多个向量长度不同时,就会先发生vector recycling,长度一致后,向量的各位置上的元素再分别运算。例子如下:
# 所谓的向量和标量之间的运算
> sample(10) + 100
> [1] 107 104 103 109 102 101 106 110 105 108
runif(10) > 0.5
> [1] FALSE TRUE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE
# 所谓的不同长度向量之间的运算
> 1:10 + 1:2
[1] 2 4 4 6 6 8 8 10 10 12
【上一篇:73.关于向量基础知识】
[【下一篇:75.关于原子向量类型的强制转换和向量元素的命名】(https://www.jianshu.com/p/22884b92dee0)
网友评论