一步步学R(2)

系列连载

一步步学R(1)
一步步学R(2)

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混合操作