2.9 小测

2.9.1 基础

  1. 向量取子集和逻辑运算。

    x <- c(3, 4, 6, 1, NA, 8, 2, 5, NA, 9, 7)

    x[-c(1, 3)], x[(length(x)-3):length(x)], x[x < 5], x[!(x < 5)]的计算结果分别是?如何得到(不包含NA的)所有小于5的值的向量?

  2. 转换年份到世纪。写一个名为as.century()的函数,把存储着年份的向量,比如years <- c(2014, 1990, 1398, 1290, 1880, 2001),转换成对应的世纪(注意,19XX年是20世纪),像这样:

    as.century(c(2014, 1990, 1398, 1290, 1880, 2001))
    #> [1] 21 20 14 13 19 21
  3. 分割时间为时和分。写名为hour(), minute()的函数,使得:

    times <- c(0512, 0719, 2358, 0501)
    hour(times)
    #> [1]  5  7 23  5
    minute(times)
    #> [1] 12 19 58  1
  4. 斐波那契数列。
  • 背景:斐波那契数列是指\(F = [1, 1, 2, 3, 5, 8, ...]\)24,其中:
    • \(F_1 = 1\)\(F_2 = 1\)
    • \(F_3\)开始,\(F_i = F_{i-2} + F_{i-1}\)
  • (也有\(F_0=0, F_1=1\)的说法,但是为了方便我们不用这个定义)
  • 题目:创建一个函数名为fibon()的函数,使得fibon(i)
    • \(i\in \mathbb{Z}^+\)时,返回向量\([F_1, F_2, \ldots, F_i]\)
    • \(i\notin \mathbb{Z}^+\)时,返回"请输入一个正整数作为`fibon()`的参数。"25
  • 提示:
    • 虽然在R中整数用1L, 2L等表示,用户在被指示“输入整数”的时候很有可能输入的是2而不是2L. 2是否等于2L?如果是,如何利用它检测输入的是否是整数?(22L都要被判定为“是整数”)
    • 斐波那契数列前两位是定义,从第三位开始才是计算得出的。

使用例:

fibon(10); fibon(-5)
#>  [1]  1  1  2  3  5  8 13 21 34 55
#> [1] "请输入一个正整数。"

2.9.2 进阶

  1. seq(0, 20, 5), seq(by = 5, 0, 20, 和seq(by = 5, 0, y = 30, 20)的结果分别是什么?为什么?(你可能需要参考第2.8.2节和第2.8.4节)

  2. 分别用sapply(), rep(), 和rapply()创建第2.7.4节提到的数列:\[x = \left(1\times1\times1, 1\times1\times2\ldots, 40\times50\times59, 40\times50\times60\right)\]

  3. 质数表。创建一个prime.list()函数,使prime.list(i)得到\((2, 3, 5, 7, 11, ... n)\), 其中i为大于或等于3的整数,\(n\)为小于i的最大质数。

    prime.list(100)
    #>  [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83
    #> [24] 89 97

    你能想到几种方法?哪一种更快?为什么?

  4. 判断一个数是否是质数。写一个函数,判断一个数是否是质数。

2.9.3 挑战

  1. 使用且仅使用function(), c(), list(), paste(), print()函数,<-, $, ==符号,和if,实现这样的效果:

    Pigeon(), Turtle(), Cat()分别创建一只鸽子, 一只乌龟和一只猫(即产生一个list,各自的元素展示如下):

    Guoguo <- Pigeon("Guoguo")
    Felix <- Cat("Felix", "TRUE")
    Kazuya <- Turtle("Kazuya")
    
    str(Guoguo)
    #> List of 5
    #>  $ name         : chr "Guoguo"
    #>  $ common_name  : chr "pigeon"
    #>  $ binomial_name: chr "Columba livia"
    #>  $ speak        : chr "coo"
    #>  $ greet        :function (time = "not_specified")  
    #>   ..- attr(*, "srcref")= 'srcref' int [1:8] 6 12 12 3 12 3 6 12
    #>   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7fae4dc5d820>
    str(Kazuya)
    #> List of 5
    #>  $ name         : chr "Kazuya"
    #>  $ common_name  : chr "turtle"
    #>  $ binomial_name: chr "Trachemys scripta elegans"
    #>  $ speak        : logi NA
    #>  $ greet        :function (time = "not_specified")  
    #>   ..- attr(*, "srcref")= 'srcref' int [1:8] 6 12 12 3 12 3 6 12
    #>   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7fae4dc5d820>
    str(Felix)
    #> List of 6
    #>  $ name         : chr "Felix"
    #>  $ common_name  : chr "cat"
    #>  $ binomial_name: chr "Felis catus"
    #>  $ speak        : chr "meow"
    #>  $ greet        :function (time = "not_specified")  
    #>   ..- attr(*, "srcref")= 'srcref' int [1:8] 6 12 12 3 12 3 6 12
    #>   .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x7fae4dc5d820> 
    #>  $ sterilized   : chr "TRUE"

    注意,鸽子,乌龟和猫都有名字 (name),通称 (common_name),学名 (binomial_name),和打招呼函数 (greet());此外,乌龟没有叫声speak(),猫额外地有绝育sterilized信息。可以这样查看信息和使用打招呼函数:

    Felix$binomial_name
    #> [1] "Felis catus"
    Kazuya$greet("afternoon")
    #> [1] "Good afternoon, I'm a turtle and my name is Kazuya"

    其中greet()的参数如果是morning, afternoonevening,则返回"Good <时间段> ...",否则返回"Hi ...".

    此外,另写两个仅对这些宠物使用的函数binomial_name()greet(),使之能够这样使用:

    binomial_name(Kazuya)
    #> [1] "Trachemys scripta elegans"
    greet(Guoguo)
    #> [1] "Hi, I'm a pigeon and my name is Guoguo"

    你可能需要的额外信息:

    鸽子,乌龟和猫的学名分别为Columba livia, Trachemys scripta elegans, Felis catus.

    paste()函数把多个字符串拼接成一个,其中参数sep指定连接符号,默认为空格:

    x <- "world"
    paste("Hello", x, "Bye", x, sep = "---")
    #> [1] "Hello---world---Bye---world"

  1. 也有\(F_0=0, F_1=1\)的说法,但是为了方便我们不用这个定义。

  2. 虽然正规的做法是制造一个错误/警告