R 语言作为我工作使用的第一门语言(有点初恋女友的感觉,羞涩), 所以颇有感情,也是它让我认识到了很多勤奋好学又独立的优秀的妹纸们(可惜她们都不是我的女票,泪崩),但是在现在 python 如日中天,连 kaggle 上的数据科学家们八成,甚至是九成都在使用 python 了,所以不能怪哥移情别恋,是现实太残酷。目前个人觉得是 Rstudio 公司撑起了 R 的商业应用,虽然微软爸爸也之前也收购过R,但是还是觉得 Rstudio 家产品都很 nice。

  作为 R 系列的开篇,废话多一点,我主要会从编程技术角度来分享一下 R 的特性,这些是使用 R 的童鞋们在平时可能不会注意到的,也是导致写出来的 R 代码充分的发挥出了它的弱点。

  首篇分享三个 R 的特性:

  • 均是函数
  • 延时计算
  • 循环填充


    事实胜于雄辩,用代码说话最具有说服力

一. 均是函数:

# 正常加法运算
1 + 1
# `+` 函数调用
`+`(1, 1)
# 正常的赋值操作
a <- 1
# `<-` 函数调用
`<-`(a, 1)

  没错,你没有看错,因为 R

# 小括号
`(`
# .Primitive("(")
# 大括号
`{`
# .Primitive("{")
# 逻辑运算与
`&&`
# .Primitive("&&")

R

二.延时计算 :

f1 <- function(x, y) x + 1
f1(1)
# [1] 2
f2 <- function(x, y) x + y
f2(1)
# Error in f2(1) : 缺少参数"y",也没有缺省值

C++ 这种编译型语言中无用参数会报出警告,而 f2 函数中y参与了运算,而在函数调用时没有传入该参数,所以会报错。
  同样知道这些有什么卵用?明白这样的机制就要注意创建函数时候避免构造无用参数,因为过多参数也会对代码造成开销,参数越少函数效率越高。
三.循环填充 :

data.frame(1:5, 1:10)
#   X1.5 X1.10
# 1     1     1
# 2     2     2
# 3     3     3
# 4     4     4
# 5     5     5
# 6     1     6
# 7     2     7
# 8     3     8
# 9     4     9
# 10    5    10
data.frame(1:5, 1:11)
Error in data.frame(1:5, 1:11) : 参数值意味着不同的行数: 5, 11

循环填充,第一行代码中第二列向量是第一列向量的整数倍,所以第一列向量自动扩充自己和第二列向量等长。而第二行代码因为不是整数倍的关系,无法完成填充,但是单向量间的运算可以非整数倍填充。

1 + 1:10
# [1]  2  3  4  5  6  7  8  9 10 11
1:2 + 1:10
# [1]  2  4  4  6  6  8  8 10 10 12
1:2 + 1:3
# [1] 2 4 4
# Warning message:
# In 1:2 + 1:3 : 长的对象长度不是短的对象长度的整倍数

  第一行代码向量 1 将自己循环了 10 次变成了 c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1) 与向量 1:10 完成计算,第二行代码 向量 1:2 将自己循环了 5 次变成了 c(1, 2, 1, 2, 1, 2, 1, 2, 1, 2) 与向量 1:10 完成计算, 第三行代码向量 1:2 将自己循环了 2 次 变成了 c(1, 2, 1) 与向量 1:3 完成了计算,虽然成功完成了计算,但是这里报出了一个警告。
  同样知道这些又有什么卵用呢?知道这样机制后,可以避免写显式的循环来增加不必要的函数调用开销,因为 R 本身会完成这样的填充。