2  工作流程:基础

你现在已经有了一些运行 R 代码的经验。我们没有给你很多细节,但你显然已经掌握了基础知识,否则你早就沮丧地把这本书扔掉了!当你开始用 R 编程时,感到沮丧是正常的,因为它对标点符号的要求非常严格,即使一个字符放错了位置也会导致它报错。但是,尽管你应该预料到会有些沮丧,但请放心,这种经历是典型且暂时的:每个人都会遇到,而克服它的唯一方法就是不断尝试。

在继续之前,让我们确保你已经牢固掌握了运行 R 代码的基础,并且了解一些最有用的 RStudio 功能。

2.1 编码基础

让我们回顾一些我们为了让你尽快开始绘图而省略的基础知识。你可以使用 R 进行基本的数学计算:

1 / 200 * 30
#> [1] 0.15
(59 + 73 + 2) / 3
#> [1] 44.66667
sin(pi / 2)
#> [1] 1

你可以使用赋值运算符 <- 创建新对象:

x <- 3 * 4

注意,x 的值没有被打印出来,它只是被存储了。如果你想查看这个值,可以在控制台中输入 x

你可以使用 c() 将多个元素 (c) 并成一个向量:

primes <- c(2, 3, 5, 7, 11, 13)

对向量的基本算术运算会应用于向量的每个元素:

primes * 2
#> [1]  4  6 10 14 22 26
primes - 1
#> [1]  1  2  4  6 10 12

所有你用来创建对象的 R 语句,即赋值 (assignment) 语句,都具有相同的形式:

object_name <- value

在读这段代码时,在脑海里默念“对象名 gets 值”。

你会进行大量的赋值操作,而输入 <- 很麻烦。你可以使用 RStudio 的键盘快捷键来节省时间:Alt + -(减号)。注意 RStudio 会自动在 <- 周围加上空格,这是一个很好的代码格式化习惯。好的代码有时读起来也很费劲,所以请多使用空格,让你的眼睛休息一下。

2.2 注释

R 会忽略那一行中 # 之后的所有文本。这允许你编写注释 (comments),即被 R 忽略但供其他人类阅读的文本。我们有时会在示例中包含注释,以解释代码的作用。

注释对于简要描述后续代码的功能非常有帮助。

# 创建一个素数向量
primes <- c(2, 3, 5, 7, 11, 13)

# 将素数乘以 2
primes * 2
#> [1]  4  6 10 14 22 26

对于像这样简短的代码,为每一行代码都留注释可能没有必要。但是随着你编写的代码变得越来越复杂,注释可以为你(和你的合作者)节省大量时间来理解代码中的操作。

使用注释来解释你代码的原因 (why),而不是方式 (how) 或内容 (what)。代码的内容方式总是可以通过仔细阅读来弄清楚,尽管可能很繁琐。如果你在注释中描述了每一步,然后又更改了代码,你就必须记得也要更新注释,否则将来你再看代码时会感到困惑。

弄清楚为什么这么做要困难得多,甚至是不可能的。例如,geom_smooth() 有一个名为 span 的参数,它控制曲线的平滑度,值越大曲线越平滑。假设你决定将 span 的值从默认的 0.75 改为 0.9:未来的读者很容易理解发生了什么,但除非你在注释中记录下你的想法,否则没人会明白你为什么要更改默认值。

对于数据分析代码,使用注释来解释你的整体攻击计划,并在遇到重要见解时记录下来。没有办法从代码本身重新捕获这些知识。

2.3 名字里有什么?

对象名必须以字母开头,并且只能包含字母、数字、_.。你希望你的对象名具有描述性,所以你需要为多个单词采用一种命名约定。我们推荐蛇形命名法 (snake_case),即用 _ 分隔小写单词。

i_use_snake_case
otherPeopleUseCamelCase
some.people.use.periods
And_aFew.People_RENOUNCEconvention

我们将在 Chapter 4 讨论代码风格时再次回到命名问题。

你可以通过输入对象名来查看它:

x
#> [1] 12

再进行一次赋值:

this_is_a_really_long_name <- 2.5

要查看这个对象,试试 RStudio 的自动补全功能:输入 “this”,按 TAB 键,继续添加字符直到你有一个唯一的前缀,然后按回车。

假设你犯了一个错误,this_is_a_really_long_name 的值应该是 3.5,而不是 2.5。你可以使用另一个键盘快捷键来帮助你修正。例如,你可以按 ↑ 键调出你输入的最后一条命令并进行编辑。或者,输入 “this” 然后按 Cmd/Ctrl + ↑ 来列出你输入过的所有以这些字母开头的命令。使用箭头键导航,然后按回车键重新输入命令。将 2.5 改为 3.5 并重新运行。

再进行一次赋值:

r_rocks <- 2^3

让我们试着查看它:

r_rock
#> Error: object 'r_rock' not found
R_rocks
#> Error: object 'R_rocks' not found

这说明了你和 R 之间的隐含契约:R 会为你做繁琐的计算,但作为交换,你的指令必须完全精确。否则,你很可能会得到一个错误,说找不到你正在寻找的对象。拼写错误很重要;R 无法读懂你的心思说,“哦,他们输入 r_rock 时可能指的是 r_rocks”。大小写也很重要;同样,R 无法读懂你的心思说,“哦,他们输入 R_rocks 时可能指的是 r_rocks”。

2.4 调用函数

R 有大量内置函数,调用方式如下:

function_name(argument1 = value1, argument2 = value2, ...)

让我们试着用 seq() 来创建规则的数字 (seq) 列,同时学习更多 RStudio 的实用功能。输入 se 然后按 TAB 键。一个弹出窗口会显示可能的补全选项。通过输入更多字符(一个 q)来明确指定 seq(),或者使用 ↑/↓ 箭头来选择。注意弹出的浮动工具提示,它会提醒你函数参数和用途。如果你需要更多帮助,按 F1 键可以在右下角的帮助标签页中获取所有详细信息。

当你选定了想要的函数后,再次按 TAB 键。RStudio 会为你添加匹配的开括号 (() 和闭括号 ())。输入第一个参数的名称 from,并将其设置为 1。然后,输入第二个参数的名称 to,并将其设置为 10。最后,按回车键。

seq(from = 1, to = 10)
#>  [1]  1  2  3  4  5  6  7  8  9 10

我们通常会省略函数调用中前几个参数的名称,所以我们可以这样重写:

seq(1, 10)
#>  [1]  1  2  3  4  5  6  7  8  9 10

输入以下代码,注意 RStudio 对成对的引号也提供了类似的辅助:

x <- "hello world"

引号和括号必须总是成对出现。RStudio 会尽力帮助你,但你仍然可能搞砸,导致不匹配。如果发生这种情况,R 会显示续行符 “+”:

> x <- "hello
+

+ 告诉你 R 正在等待更多输入;它认为你还没有完成。通常,这意味着你忘了一个 " 或一个 )。要么加上缺失的配对符号,要么按 ESCAPE 键中止表达式并重试。

注意,右上角的环境 (environment) 标签页显示了你创建的所有对象:

RStudio 的环境标签页,在全局环境中显示了 r_rocks、this_is_a_really_long_name、 x 和 y。

2.5 练习

  1. 为什么这段代码不工作?

    my_variable <- 10
    my_varıable
    #> Error: object 'my_varıable' not found

    仔细看! (这可能看起来像一个无意义的练习,但训练你的大脑注意最微小的差异在编程时会大有裨益。)

  2. 调整以下每个 R 命令,使它们能够正确运行:

    libary(todyverse)
    
    ggplot(dTA = mpg) + 
      geom_point(maping = aes(x = displ y = hwy)) +
      geom_smooth(method = "lm)
  3. 按 Option + Shift + K / Alt + Shift + K。 发生了什么? 如何通过菜单达到同样的位置?

  4. 让我们重温 Section 1.6 中的一个练习。 运行以下代码行。 哪一个图被保存为 mpg-plot.png? 为什么?

    my_bar_plot <- ggplot(mpg, aes(x = class)) +
      geom_bar()
    my_scatter_plot <- ggplot(mpg, aes(x = cty, y = hwy)) +
      geom_point()
    ggsave(filename = "mpg-plot.png", plot = my_bar_plot)

2.6 小结

现在你已经对 R 代码如何工作有了更多了解,也学到了一些技巧,帮助你在未来回顾代码时能更好地理解。在下一章中,我们将继续你的数据科学之旅,教你关于 dplyr 的知识,它是 tidyverse 中帮助你转换数据的包,无论是选择重要变量、筛选感兴趣的行,还是计算汇总统计数据。