系列连载
If-Else
R 种的If-Else结构并没有比较特殊的地方,仍然支持两种结构:
if (condition) {
// Do Something
} else {
// Do Otherthing
}
或者如下:
if (condition) {
// Do Something
} else if (condition2) {
// Do Otherthing
} else {
// Do Else
}
但是在R中,对于If-else有一个可以简化的地方,如:
if (x > 100) {
y <- 10
} else if (x < 100) {
y <- 11
} else {
y <- 5
}
可以简化成:
y <- if (x > 100) {
10
} else if (x < 100) {
11
} else {
5
}
For
For语句的语法也非常简单:
for (i in 1:10) {
print(i)
}
seq_along 函数是for循环中可以注意的一个点。它的参数是一个vector,如x <- c('a', 'b')
,调用seq_along(x)
会得到一个序列,长度为2,值为1,2。因此,print(x[1])
就等于 a
。
While
同样简单:
while (condition) {
// Do studyy
}
Repeat
repeat是R中特有的一种逻辑结构,简单来理解就是死循环,想要退出的唯一方式是显式使用break
。
repeat {
x <- something()
if (A) {
break
} else {
x <- x + 1
}
}
Next
next
就是其他语言中的continue
for (i in 1:100) {
if (i < 20) {
next
}
// Do other
}
函数
R中的函数可以没有显式的return
,默认返回最后一句语句。
add2 <- function(x, y) {
x + y
}
和其他语言一样,你可以给参数设置默认值,如
add2 <- function(x, y = 10) {
x + y
}
R中的函数参数优点类似于JavaScript,可以不用赋值完全,前提是你用不到。而且,对于R中的参数,你可以打乱参数传递,只要你前面加上了行参的名称,
比如
add2 <- function(x, y) {
x + y
}
你可以通过add2(y = 5, x = 7)
来进行调用。
可变参数
在R中也是有可变参数的,即...
。
myplot <- function(x, y, type = 1, ...) {
plot(x, y, type, ...)
}
同样,...
也可以用在泛型函数中,后续学习中我们会说到。
**不过,与其他编程语言所不同的是,R中的可变参数可以放在函数列表的前面,如
function(..., sep = " ", collsape = NULL)
调用如上的这种函数,必须显式的通过函数参数名称来调用后续参数,如
function("haha", "heihei", sep = ",")
变量作用域
使用变量
当你使用一个R语言中的变量时,比如x,你有没有想过x究竟是存在于哪里呢?
有些人会说,我定义的呀,比如x <- 5
,那么对于那些默认函数,比如vector()
呢?
所以,这就涉及到R中的Symbol binding(其他语言的变量查找)了。
在R中,查找顺序是这样的。
[1] ".GlobalEnv" "tools:rstudio" "package:stats" "package:graphics" "package:grDevices"
[6] "package:utils" "package:datasets" "package:methods" "Autoloads" "package:base"
默认查找的是.GlobalEnv,依次类推。
如果你还通过library()
函数加载了其他package,如ggplot2,那么查找顺序是
[1] ".GlobalEnv" "package:ggplot2" "tools:rstudio" "package:stats" "package:graphics"
[6] "package:grDevices" "package:utils" "package:datasets" "package:methods" "Autoloads"
[11] "package:base"
也就是用户加载的package会自动加到除了.GlobalEnv之外的任意搜索顺序前。
如果要查看最新的搜索顺序,可以通过search()
作用域
R中的作用域,是Lexical Scoping,也就是静态作用域,也就是JavaScript的作用域。
好了,我不多说了,如果想学习更多冠以静态作用域的话,看我的JavaScript博客部分。
当然,如果你不懂,你可以通过如下函数帮助你理解。
ls(environment(functionName))
get(variableName, environment(functionName))
一言以蔽之,lexcial scoping可以简单理解为你函数中需要的变量,是通过其定义时环境进行查找。
Data and Times
R中的时间表示,采用了一种特殊的数据结构。
Date是通过Date这一数据结构表示,而Time是通过POSIXct或者POSIXlt表示。
- Date是不包含Time的,只显示年、月、日。
- Date的内部储存是计算1970-01-01到当前时间之间的天数。
- Time的内部储存是计算1979-01-01到当前时间之间的秒数。
可以采用as.Date
构建Date,如as.Date("1970-01-01")
而Time相对来说比较复杂,我们首先来看看Posixlt
的表现形式。
我们输入p<- Sys.time()
获取当前时间,结果是"2015-12-27 00:59:18 CST"
,然后我们调用unclass(p)
来看看其构成,结果如下:
[1] "sec" "min" "hour" "mday" "mon" "year" "wday" "yday" "isdst" "zone" "gmtoff"
这表明,通过Posixlt
表征的Time
,其内部是由一系列成分组成的集合。我们可以通过p$wday
来查看今天是周几。
而Posixct
就是就算1970-01-01到当前时间的描述,是个非常大的Integer。
你可以对Date或者Time进行大小比较操作,但是注意,不能讲Date和Time混合操作