Top 10错误在R中以及如何修复

Top 10个在R中常见的错误和如何修复它们

如果你刚开始学习R,你会经常遇到代码错误,导致无法运行。我记得当我刚开始使用R时,我的代码中经常出现错误,以至于我几乎放弃学习这个编程语言。我甚至记得有几次我回到Excel中完成我的分析,因为我找不到问题的根源。

幸运的是,尽管一开始很困难,我还是坚持下去了。今天,即使我写R代码时仍然经常遇到错误,但通过经验和练习,解决它们所需的时间越来越短。如果你也在起步阶段遇到困难,不用担心,这很正常:每个人在学习一门新的编程语言时都会遇到一些挫折(这不仅限于R)。

在这篇文章中,我将重点介绍R中常见的10个错误以及如何修复它们。当然,错误取决于你的代码和分析,所以不可能涵盖所有错误(而且谷歌比我更擅长这个)。然而,我想重点关注一些在学习R时常见的语法错误,有时候在找到解决方案之前可能需要很长时间,而解决方案可能就在我们眼前。

这个列表是基于我个人的经验以及我教R时学生们遇到的错误。由于这个列表是不全面的,欢迎你在文章末尾的评论区分享你在使用R时经常遇到的错误。

对于每个错误,我提供了例子和解决方案来修复它们。在文章末尾,我还提到了一些警告(严格来说,这些并不是错误)。

1. 括号、花括号、方括号或引号不匹配

一个相当琐碎但仍然相当频繁的错误是缺少括号、花括号、方括号或引号。

这种类型的错误适用于许多编程语言。例如,在R中:

## 缺少闭合括号:mean(c(1, 7, 13)     ## 缺少"else"之前的花括号:x <- 7 if(x > 10) {  print("x > 10") else {  print("x <= 10") }  ## 缺少方括号:summary(ggplot2::diamonds[, "price")## 第二个元素缺少闭合引号:grp <- c("Group 1", "Group 2) grp

这些错误在代码很基础的时候比较容易发现,但在更复杂的代码中可能很难发现,例如:1

for (i in y) {  for (j in x) {    p <- ggboxplot(dat,      x = colnames(dat[j]), y = colnames(dat[i]),      color = colnames(dat[j]),      legend = "none",      palette = "npg",      add = "jitter"    )    print(      p + stat_compare_means(aes(label = paste0(..method.., ", p-value = ", ..p.format..),        method = method1, label.y = max(dat[, i], na.rm = TRUE)      )      + stat_compare_means(comparisons = my_comparisons, method = method2, label = "p.format")    )  }

幸运的是,如果你使用RStudio,2 当你打开一个括号、花括号、方括号或引号时,相应的闭合符号将自动写入。

请记住,在安装包时,你必须用(单引号或双引号)引号将包名括起来:

## 不正确:install.packages(ggplot2)

## Error in install.packages : object 'ggplot2' not found

而应该选择以下两个选项之一:

# install.packages("ggplot2")# install.packages('ggplot2')

解决方案

当然,解决方案就是将所有的开括号、花括号、方括号和引号与其闭合配对:

均值(c(1, 7, 13))

## [1] 7

x <- 7if (x > 10) { print(“x > 10”)} else { print(“x <= 10”)}

## [1] “x <= 10”

summary(ggplot2::diamonds[, “price”])

## price ## Min. : 326 ## 1st Qu.: 950 ## Median : 2401 ## Mean : 3933 ## 3rd Qu.: 5324 ## Max. :18823

grp <- c(“Group 1”, “Group 2”)grp

## [1] “Group 1” “Group 2”

注意:

确保正确放置逗号:

## 错误(逗号放错位置):c(“Group 1,” “Group 2”)

## Error: unexpected string constant in “c(“Group 1,” “Group 2″”

## 也不正确(逗号遗漏):c(“Group 1” “Group 2”)

## Error: unexpected string constant in “c(“Group 1” “Group 2″”

## 正确:c(“Group 1”, “Group 2”)

不要混用单引号和双引号表示同一个元素:

## 不正确:c(“Group 1′)

## 正确:c(“Group 1”)

## 也正确:c(‘Group 1’)

请注意,c(‘Group 1’, “Group 2”)不会产生错误,但为了一致性,不建议在同一个向量中混用单引号和双引号。

2. 使用未安装或未加载的函数

如果遇到以下错误:“Error in … : could not find function ‘…’”,例如:

it means you are trying to use a function belonging to a package which is not yet installed or loaded.

解决方案

要解决此错误,您必须安装该包(如果尚未安装),并使用install.packages()和library()函数加载它:

install package:install.packages(“ggplot2”)
load package:library(ggplot2)

如果您不确定这两个函数的用法,请查看有关在R中安装和加载包的更多详细信息。

3. 函数,变量,数据集,对象或包名称的拼写错误

另一个常见错误是拼写错误的函数名,变量名,数据集名,对象名或包名,例如:

typo in function name:maen(c(1, 7, 13))

Error in maen(c(1, 7, 13)) : could not find function “maen”

typo in variable name:summary(ggplot2::diamonds[, “detph”])

Error: Column ‘detph’ doesn’t exist

typo in dataset name:data <- data.frame( x = rnorm(10), y = rnorm(10))summary(dta[, 2])

Error in summary(dta[, 2]) : object ‘dta’ not found

typo in object name:test <- c(1, 7, 13)mean(tset)

Error in mean(tset) : object ‘tset’ not found

typo in package name:library(“tydiverse”)

Error in library(“tydiverse”) : there is no package called ‘tydiverse’

解决方案

确保正确拼写所有函数,变量,数据集,对象和包:

请注意,R是区分大小写的;对于R,mean()被视为与Mean()不同的函数!

mean(c(1, 7, 13))

## [1] 7

summary(ggplot2::diamonds[, "depth"])

##      depth      ##  最小值   :43.00  ##  第一四分位数:61.00  ##  中值 :61.80  ##  平均值   :61.75  ##  第三四分位数:62.50  ##  最大值   :79.00

data <- data.frame(  x = rnorm(10),  y = rnorm(10))
data[, 2]

##  [1]  1.3048697  2.2866454 -1.3888607 -0.2787888 -0.1333213  0.6359504##  [7] -0.2842529 -2.6564554 -2.4404669  1.3201133

test <- c(1, 7, 13)
mean(test)

## [1] 7

library(tidyverse)

## ── 载入 tidyverse 核心包 ──────────────────────── tidyverse 2.0.0 ──## ✔ dplyr     1.1.3     ✔ readr     2.1.4## ✔ forcats   1.0.0     ✔ stringr   1.5.0## ✔ ggplot2   3.4.3     ✔ tibble    3.2.1## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0## ✔ purrr     1.0.2     ## ── 冲突 ────────────────────────────────────────── tidyverse_conflicts() ──## ✖ dplyr::filter() 掩盖了 stats::filter()## ✖ dplyr::lag()    掩盖了 stats::lag()## ℹ 使用冲突包()可以将所有冲突变为错误

如果您确定正确拼写了对象、函数或数据集,但仍然出现“找不到对象’…’”的错误,请确保在调用之前定义了对象/函数/数据集!

经常发生这样的情况,学生让我来看看他/她的电脑,因为他/她运行的代码与我完全相同,但无法正常工作。大多数情况下,如果他/她的代码确实与我的完全相同,那么他/她只是在运行包含该对象/函数/数据集的代码之前没有执行它。换句话说,他/她只是尝试使用未定义的对象或变量。

请记住,在R脚本中编写代码(与控制台相反)并不意味着它被编译。您实际上必须运行它(通过单击“运行”按钮或使用键盘快捷键),以便执行代码并稍后使用它。如果您仍然遇到困难,请参阅R和RStudio基础知识

4. 函数中缺失、不正确或拼写错误的参数

大多数R函数需要参数。例如,rnorm()函数至少需要观测值数量,通过参数n指定。

如果您未指定必需的参数,或者错误地指定了参数,则代码将无法运行。此外,如果拼写参数错误,结果可能与预期不符:

## 缺失必需参数:rnorm()

## Error in rnorm() : argument "n" is missing, with no default

## 错误的参数:rnorm(n = 3, var = 1)

## Error in rnorm(n = 3, var = 1) : unused argument (var = 1)

## 拼写错误的参数:mean(c(1, 7, 13, NA), narm = TRUE)

## [1] NA

最后一段代码没有抛出错误,但结果并不是我们想要的。

解决方案

为了解决这些错误,请确保至少指定函数的所有必需参数以及正确的参数:

  • 对于rnorm()函数来说,除了观测值数量n外,还可以指定标准差sd(而不是方差var)。
  • 要去掉NA,可以使用na.rm(而不是narm)。
rnorm(n = 3, sd = 1)

## [1] -0.3066386 -1.7813084 -0.1719174

mean(c(1, 7, 13, NA), na.rm = TRUE)

## [1] 7

如果你不熟悉函数的参数,你总可以通过使用?function_namehelp(function_name)来查看文档,例如:

?rnorm()## 或者:help(rnorm)

5. 错误、不合适或不一致的数据类型

R中有几种数据类型,主要包括:

  • 数值型
  • 字符型
  • 因子型
  • 逻辑型

你应该知道,某些操作和分析只适用于特定类型的数据。

例如,计算因子型或字符型变量的均值是不合适的:

gender <- factor(c("female", "female", "male", "female", "male"))mean(gender)

## 警告:mean.default(gender): 参数不是数值型或逻辑型:将返回NA

## [1] NA

同样地,虽然在技术上是可能的,但对于连续定量变量绘制条形图几乎没有意义,因为在大多数情况下,每个值的频率都是1:

barplot(table(rnorm(10)))

(顺便提一下,如果你的数据还没有以表格形式显示,请别忘了在barplot()函数中加入table()。)

解决方法

确保根据所关注的变量使用适当的操作和分析类型。

例如:

  • 对于因子型变量,计算频数和/或相对频数,并绘制条形图是更为合适的
  • 对于连续定量变量,计算均值、中位数等,并绘制直方图、箱线图等是更为合适的
  • 对于逻辑型变量,可以使用平均值、频数表和条形图
  • 对于字符型变量,最适合的是绘制词云(除非变量可以被视为因子型变量,因为不同水平不太多)

接下来我们在R中演示这些例子:4

## 因子型:table(gender)

## gender## female   male ##      3      2

prop.table(table(gender))

## gender## female   male ##    0.6    0.4

barplot(table(gender))

## 连续定量型:x <- rnorm(100)summary(x)

##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. ## -2.99309 -0.74143  0.01809 -0.08570  0.58937  2.70189

par(mfrow = c(1, 2)) ## combine two plotshist(x)boxplot(x)

## 逻辑型:x <- c(TRUE, FALSE, FALSE, TRUE, TRUE)mean(x)

## [1] 0.6

table(x)

## x## FALSE  TRUE ##     2     3

barplot(table(x))

对于感兴趣的读者,可以查看不同类型数据在R中最常见的描述性统计

请注意,与描述性统计一样,统计检验的选择取决于变量的类型。根据变量的数量和类型,参考流程图来帮助你选择最合适的统计检验。

与上述提到的错误有关的一个错误是数据类型不一致。通过以下示例进行实践:

x <- c(2.4, 3.7, 5.1, 9.8)class(x)

## [1] "numeric"

y <- c(2.4, 3.7, 5.1, "9.8")class(y)

## [1] "character"

如你所见,向量x是数值型,而向量y是字符型。这是因为y的最后一个元素被引号包围(因此被认为是字符串而不是数值),整个向量变成字符型。

当你将数据集导入R时,如果一些变量的一个或多个元素没有正确编码,就会发生这种情况,导致整个变量被R视为字符变量。

为了避免这种情况,一个良好的做法是在导入后检查数据集的结构(使用str()),以确保所有的变量具有期望的格式。如果不是,可以在初始文件中更正值,或在R中更改格式(使用as.numeric())。

6. 在ggplot2中忘记使用+符号

如果你刚学习使用ggplot2包进行可视化(我强烈推荐它!),一个常见的错误是忘记使用+符号。

你知道使用ggplot2制作的可视化是通过添加多个图层构建的:

## 加载包:library(ggplot2)## 第一层,数据集:ggplot(data = diamonds) +  ## 第二层,美学:  aes(x = cut, y = price) +  ## 第三层,绘图类型:  geom_boxplot() +  ## 添加更多图层:  theme_minimal()

解决方案

对于所有使用ggplot2的图形,请在每一层后面添加+符号,除了最后一层

7. =和==之间的误解

R中的赋值可以通过三种方式进行,从最常见到最不常见:

  1. <-
  2. =
  3. assign()

第二种方法,即=,不应与==混淆。

实际上,使用任一上述方法之一来为R中的对象赋值是为了保存对象。例如,如果我们想保存向量(1, 3, 7)并将该向量重命名为x,我们可以写成:

x <- c(1, 3, 7)## 或者:x = c(1, 3, 7)## 或者:assign("x", c(1, 3, 7))

执行这段代码时,您会看到大小为3的向量x出现在“环境”选项卡中(如果您使用RStudio的默认视图,则为右上面板):

从现在开始,我们可以通过使用它的名称来简单地调用该向量:

x

## [1] 1 3 7

绝对不可以使用==来赋值一个对象:

## 如果我们想要将c(1, 3, 7)赋值给x,则是不正确的:x == c(1, 3, 7)

那么,您可能会想,什么时候需要使用==呢?实际上,它用于等号的使用情况。

我理解这可能在此刻还是有点抽象和混淆,所以让我们假设以下两个情况作为示例(这是我们使用==的最常见的两种情况):

  1. 我们想要检查一个已分配对象或变量是否符合某些条件,以及
  2. 我们想要基于一个或多个条件对数据框进行子集操作。

对于这些示例,假设有5名儿童的样本

## 创建数据框:dat <- data.frame(  Name = c("Mary", "Linda", "James", "John", "Patricia"),  Age = c(7, 10, 3, 9, 7),  Gender = c("Girl", "Girl", "Boy", "Boy", "Girl"))## 打印数据框:dat

##       Name Age Gender## 1     Mary   7   Girl## 2    Linda  10   Girl## 3    James   3    Boy## 4     John   9    Boy## 5 Patricia   7   Girl

现在让我们写一些不同的代码片段来说明这两种情况:

  • 我们想要检查变量Age是否等于向量(1, 2, 3, 4, 5)
dat$Age == 1:5

## [1] FALSE FALSE  TRUE FALSE FALSE

通过这段代码,我们询问变量Age的第一个元素是否等于1,变量Age的第二个元素是否等于2,以此类推。答案当然是FALSEFALSETRUEFALSEFALSE,因为只有第三个孩子的年龄恰好等于3岁。

  • 我们想要知道我们抽样的5名儿童中有几个是女孩:
dat$Gender == "Girl"

## [1]  TRUE  TRUE FALSE FALSE  TRUE

结果显示第一、第二和第五个孩子是女孩,而第三和第四个孩子不是女孩。

如果您写下以下任意一行代码:

## 这会覆盖Age和Gender:dat$Age = 1:5dat$Gender = "Girl"

实际上,您会覆盖AgeGender变量,这样我们的5个孩子的年龄将从1到5(第一个孩子1岁,第五个孩子5岁),并且他们全部都是女孩。

  • 现在假设我们想要基于某个条件对数据框进行子集操作,也就是说,我们只想提取年龄为7岁的孩子:
subset(dat, Age == 7)

##       Name Age Gender## 1     Mary   7   Girl## 5 Patricia   7   Girl

如果您不想使用subset函数,您还可以使用方括号:

dat[dat$Age == 7, ]

##       Name Age Gender## 1     Mary   7   Girl## 5 Patricia   7   Girl

正如您在之前的例子中所看到的,我们不想分配任何东西。相反,我们在问“这个变量或向量是否等于其他东西?”。为了满足这个特定的需求,我们使用==

所以总结一下,由于技术原因并为了区分这两个概念,R使用=表示赋值,使用==表示等号。确保理解这两者之间的区别,以避免任何错误。

8. 选择了未定义的列

如果您习惯使用方括号[]对数据框进行子集操作,而不是使用subset()filter()函数,您可能会遇到“Error in [.data.frame(…) : undefined columns selected”错误。

当在子集数据集时,R不能理解您想要使用的列时,就会发生这种情况。

考虑之前介绍的5个儿童的样本,以下代码将会引发错误:

dat[dat$Age == 7]

## Error in `[.data.frame`(dat, dat$Age == 7) : undefined columns selected

因为它没有指定列维度。

解决方案

请记住,R中的数据框有两个维度:

  1. 行(每个实验单元一行),
  2. 列(每个变量一列)

并且按照这个特定顺序(先行,然后列)!

由于数据框有两个维度,当您调用dat[]时,R期望有两个维度。

具体地说,它希望先是第一个维度,然后是第二个维度,用逗号分隔

dat[dat$Age == 7, ]

##       Name Age Gender
## 1     Mary   7   Girl
## 5 Patricia   7   Girl

这段代码的意思是,我们提取所有Age等于7(第一个维度,即在逗号之前的部分)的行,对于数据集的所有变量(因为我们没有在逗号之后指定任何列)。

对于感兴趣的读者,可以了解更多在R中进行子集和操作数据的方法。

9. 导入或使用错误的数据文件问题

对于初学者来说,在R中导入数据集可能相当具有挑战性,主要是由于对工作目录的误解。

在导入文件时,R不会在计算机的所有文件夹中搜索文件。相反,它只会在一个特定的文件夹中搜索。如果您的数据集不在该文件夹中,就会出现“不能打开文件‘…’:没有这样的文件或目录”等错误:

要解决这个问题,您必须指定数据集所在的文件夹的路径。换句话说,您需要告诉R要在哪个文件夹中进行工作,因此称为工作目录。

可以使用setwd()函数或通过RStudio右下角的“文件”选项卡来设置工作目录:

另外,您也可以将数据集移动到R当前工作的目录中(可以使用getwd()查找该目录)。有关导入文件到R和有关工作目录的更多详细信息,请参考相关链接。

另一个相关问题是使用错误的文件。这种错误与之前的错误不同,您不会遇到错误,但是您的分析结果仍然是错误的。

这可能听起来很琐碎,但请确保导入和使用正确的数据文件!特别是在您拥有不同时间点的文件,并且这些文件具有相同的结构(例如每周或每月数据文件具有完全相同的变量)。我曾经遇到过报告错误周次的情况(幸运的是,没有什么严重后果)。

另外,请确保您实际使用了要包含在分析中的所有行。我曾经遇到这样的情况,为了测试模型(并避免长时间计算),我从原始数据集中提取了一个随机样本,但几乎在进行最终分析时忘记了这个抽样。

因此,在测试代码之后(并在解释最终结果之前),将抽样和过滤器移除是一个好的实践。

10. 使用$运算符时的问题

对于前10个错误的最后一个,我想重点关注两个相关的错误:

  1. “$运算符对于原子向量无效”,以及
  2. “类型为闭包的对象不可子集化”。

我将它们归为一节,因为它们在意义上相互关联,它们都涉及$运算符。

$运算符对于原子向量无效

为了理解这个错误,我们首先必须记住,原子向量是一个一维对象(通常使用c()创建)。这与数据框或矩阵不同,数据框或矩阵是二维的(即行是第一维,列对应第二维)。

当我们尝试使用$运算符($)访问原子向量的元素时,就会出现错误“$运算符对于原子向量无效”:

## 定义原子向量:x <- c(1, 3, 7)## 设置名称:names(x) <- LETTERS[1:3]## 打印向量:x

## A B C ## 1 3 7

## 访问元素C的值:x$C

## 错误:无法对原子向量使用$运算符

解决方案

$运算符不能用于提取原子向量的元素。相反,我们必须使用双括号[[]]语法:

x[["C"]]

## [1] 7

请记住$运算符可以用于数据框,所以我们也可以通过首先将原子向量转换为数据框,然后使用$运算符按名称访问元素来修复此错误:

## 将原子向量转换为数据框:x <- as.data.frame(t(x))## 打印x:x

##   A B C## 1 1 3 7

## 访问元素C的值:x$C

## [1] 7

类型为闭包的对象不可子集化

另一个错误(当学习R时,我必须承认这个错误相当晦涩和令人困惑)是以下错误提示:“类型为闭包的对象不可子集化”。

当我们尝试对函数进行子集化或访问一些元素时,就会出现此错误。以下是使用众所周知的mean()函数的示例:

mean[1:3]

## 错误:类型为闭包的对象不可子集化

在R中,我们可以对列表、向量、矩阵、数据框进行子集化,但不能对函数进行子集化。因此,它会抛出错误,因为不可能对类型为“closure”的对象进行子集化,而函数就是这种类型的对象:

typeof(mean)

## [1] "closure"

大多数情况下,当使用像mean()这样的基本函数时,不会出现此错误(因为您的目标很可能不是对函数进行子集化…)。

实际上,当尝试对命名为data的数据集进行子集化时,您很可能会遇到此错误,但该数据集在环境中未定义(例如,因为它未被正确地导入或创建)。

为了理解这个概念,请参考以下示例:

## 创建数据集:data <- data.frame(  x = rnorm(10),  y = rnorm(10))## 打印变量x:data$x

##  [1]  1.12288964  1.43985574 -1.09711377 -0.11731956  1.20149840 -0.46972958##  [7] -0.05246948 -0.08610730 -0.88767902 -0.44468400

到目前为止还不错。现在假设我们在创建数据集时犯了个错误:

## 创建数据集(有错误):data <- data.frame(x = rnorm(10)                   y = rnorm(10))

您会注意到变量xy之间缺少了一个逗号。结果,名为data的数据集没有被创建,因此也没有定义。

因此,如果我们现在尝试从该数据集data中访问变量x,R实际上将尝试对名为data的函数进行子集操作,而不是数据集data

data$x

## Error in data$x : object of type 'closure' is not subsettable

这是因为,我重复一遍,数据集data不存在,所以R会寻找一个名为data的对象,并找到一个具有该名称的函数:

class(data)

## [1] "function"

警告

警告与错误不同,它们提醒您注意某些事物,但不会阻止您运行代码。阅读这些警告是一个好习惯,因为它们可能提供有价值的信息。

有太多警告无法一一列举,但我想重点关注两个常见的警告:

  1. “通过强制转换引入的NAs”和
  2. “删除…包含非有限值的行(stat_bin())”。

通过强制转换引入的NAs

当您尝试将至少包含一个非数字值的向量转换为数值向量时,会出现此警告:

x <- c(1, 3, 7, "Emma")as.numeric(x)

## Warning: NAs introduced by coercion

## [1]  1  3  7 NA

您不需要修正它,因为这只是一个警告而不是错误。R只是告诉您,初始向量中至少有一个元素被转换为NA,因为它无法转换为数值。

删除…包含非有限值的行(stat_bin())

当您使用ggplot2绘制图形时会出现此警告。例如:

ggplot(airquality) +  aes(x = Ozone) +  geom_histogram()

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

## Warning: Removed 37 rows containing non-finite values (`stat_bin()`).

同样,由于它是一个警告,您不需要修复它。它只是告诉您感兴趣的变量中有一些缺失值(NA),并且这些缺失值被删除以构建图形。

总结

谢谢阅读。

我希望这些错误的收集能够帮助您避免一些编码错误,或者帮助您调试代码。

如果您仍然无法解决错误,我建议阅读函数的文档(如果您特别困扰某个函数),或者在网上寻找解决方案。请记住,如果您遇到错误,很有可能其他人已经在网上发布了答案(Stack Overflow通常是一个很好的资源)。

R具有陡峭的学习曲线,特别是如果您对其他编程语言不熟悉。尽管如此,通过实践和时间,您将减少越来越少的编码错误,但更重要的是,您将变得越来越熟练于在搜索引擎中输入正确的关键字,从而减少寻找解决方案的时间。

如往常一样,如果您对本文所讨论的主题有疑问或建议,请在评论中提出,以便其他读者也可以从讨论中受益。

文章由Antoine Soetewey最初发布在此处。