你碰到的最大的R-gotcha是什么?

Vin*_*nce 57 r r-faq

有一天R-gotcha让你真的感到惊讶吗?我想我们都可以分享这些.

这是我的:在列表索引中,my.list[[1]]不是my.list[1].在R的早期学到了这一点.

Sha*_*ane 42

[哈德利在评论中指出了这一点.]

当使用序列作为迭代的索引时,最好使用seq_along()函数而不是类似的函数1:length(x).

在这里,我创建一个向量,两个方法返回相同的东西:

> x <- 1:10
> 1:length(x)
 [1]  1  2  3  4  5  6  7  8  9 10
> seq_along(x)
 [1]  1  2  3  4  5  6  7  8  9 10
Run Code Online (Sandbox Code Playgroud)

现在制作矢量NULL:

> x <- NULL
> seq_along(x) # returns an empty integer; good behavior
integer(0)
> 1:length(x) # wraps around and returns a sequence; this is bad
[1] 1 0
Run Code Online (Sandbox Code Playgroud)

这可能会导致循环中出现一些混乱:

> for(i in 1:length(x)) print(i)
[1] 1
[1] 0
> for(i in seq_along(x)) print(i)
>
Run Code Online (Sandbox Code Playgroud)


edw*_*ard 35

加载数据时自动创建因子.您不假思索地将数据框中的列视为字符,这样做很有效,直到您尝试将值更改为不是某个级别的值.这会生成一个警告,但保留数据框中包含NA ...

如果R脚本出现意外错误,请检查因素是否应该受到指责.

  • @Dirk一切顺利,直到你发送一段代码给一个有不同.Rprofile的人(本周发生在我身上;) (10认同)
  • 对 - 但你可以在你的启动文件中使用`options("stringsAsFactors"= FALSE)`来改变它. (7认同)

Dir*_*tel 32

忘记将矩阵子集化为单维的drop = FALSE参数,从而删除对象类:

R> X <- matrix(1:4,2)
R> X
     [,1] [,2]
[1,]    1    3
[2,]    2    4
R> class(X)
[1] "matrix"
R> X[,1]
[1] 1 2
R> class(X[,1])
[1] "integer"
R> X[,1, drop=FALSE]
     [,1]
[1,]    1
[2,]    2
R> class(X[,1, drop=FALSE])
[1] "matrix"
R> 
Run Code Online (Sandbox Code Playgroud)


Ian*_*ows 32

删除数据框中的行将导致添加非唯一命名的行,然后输出错误:

> a<-data.frame(c(1,2,3,4),c(4,3,2,1))
> a<-a[-3,]
> a
  c.1..2..3..4. c.4..3..2..1.
1             1             4
2             2             3
4             4             1
> a[4,1]<-1
> a
Error in data.frame(c.1..2..3..4. = c("1", "2", "4", "1"), c.4..3..2..1. = c(" 4",  : 
  duplicate row.names: 4
Run Code Online (Sandbox Code Playgroud)

那么这里发生的是:

  1. 创建了四行data.frame,因此rownames是c(1,2,3,4)

  2. 第三行被删除,所以rownames是c(1,2,4)

  3. 添加第四行,R自动设置行名称等于索引,即4,因此行名称为c(1,2,4,4).这是非法的,因为行名称应该是唯一的.我不明白为什么R应该允许这种行为.在我看来,R应该提供一个唯一的行名.

  • 所以这里发生的是:1.创建一个四行data.frame,所以rownames是c(1,2,3,4)2.第三行被删除,所以rownames是c(1,2 ,4)3.添加第四行,R自动设置行名称等于索引,即4,因此行名称为c(1,2,4,4).这是非法的,因为行名称应该是唯一的.我不明白为什么R应该允许这种行为.在我看来,R应该提供一个唯一的行名. (11认同)
  • 请注意,这是print.data.frame的错误.否则代码将运行正常(带警告.) (5认同)
  • 有趣.自1988年以来,我一直在使用R和它的前辈,我以前从未见过它! (2认同)

Joh*_*ohn 23

首先,让我说我理解在二进制系统中表示数字的基本问题.然而,我认为可以轻易改进的一个问题是当十进制值超出R的典型呈现范围时数字的表示.

x <- 10.2 * 100
x
1020
as.integer(x)
1019
Run Code Online (Sandbox Code Playgroud)

我不介意结果是否表示为整数,它实际上可以表示为整数.例如,如果值真的是1020那么打印x就可以了.但是在这种情况下,当打印x时,像1020.0这样简单的事情会使得这个值不是一个整数并且不能表示为一个更明显.当存在未呈现的极小十进制分量时,R应默认为某种指示.

  • 我认为这是R作为交互式数据分析平台的传统.尝试限制显示的位数是有道理的,但看看如何完成它是很棘手的.一个可能过于聪明的替代方案(永远不会实现)将始终打印至少小数点的浮点值,即`1.000000000001`将打印为`1.`; 另一种选择是在整数之后打印一个显式的"L",但那会很难看. (2认同)

nul*_*lob 20

它可以是恼人不得不允许的组合NA,NaNInf.它们的行为不同,对其中一个的测试不一定适用于其他人:

> x <- c(NA,NaN,Inf)
> is.na(x)
[1]  TRUE  TRUE FALSE
> is.nan(x)
[1] FALSE  TRUE FALSE
> is.infinite(x)
[1] FALSE FALSE  TRUE
Run Code Online (Sandbox Code Playgroud)

然而,测试任何这些麻烦制造者最安全的方法是:

> is.finite(x)
[1] FALSE FALSE FALSE
Run Code Online (Sandbox Code Playgroud)

  • 有趣的......我一直认为"NA"是"我不知道(还)".但是我的解释不符合`is.infinite(NA)`和`is.finite(NA)`返回'FALSE`:我曾预料到`NA`. (7认同)

Sha*_*ane 18

总是测试你有什么时候会发生什么NA!

我经常需要注意的一件事(经过许多痛苦的经历)是NA价值观.R函数易于使用,但没有任何编程方式可以克服数据问题.

例如,任何带有a的净矢量运算NA都等于NA.从表面上看,这是"令人惊讶的":

> x <- c(1,1,2,NA)
> 1 + NA
[1] NA
> sum(x)
[1] NA
> mean(x)
[1] NA
Run Code Online (Sandbox Code Playgroud)

这可以外推到其他更高级别的功能中.

换句话说,缺省值通常与默认情况下的测量值一样重要.许多功能都有na.rm=TRUE/FALSE默认值; 值得花一些时间来决定如何解释这些默认设置.

编辑1:马雷克提出了一个很好的观点. NA值也可能导致索引中的混乱行为.例如:

> TRUE && NA
[1] NA
> FALSE && NA
[1] FALSE
> TRUE || NA
[1] TRUE
> FALSE || NA
[1] NA
Run Code Online (Sandbox Code Playgroud)

当您尝试创建条件表达式(对于if语句)时也是如此:

> any(c(TRUE, NA))
[1] TRUE
> any(c(FALSE, NA))
[1] NA
> all(c(TRUE, NA))
[1] NA
Run Code Online (Sandbox Code Playgroud)

当这些NA值最终作为矢量索引时,可能会出现许多意外情况.这对R来说都是很好的行为,因为这意味着你必须小心缺少值.但它可能会在一开始就引起严重的麻烦.

  • 下标很痛苦,例如.`(1:3)[c(TRUE,FALSE,NA)]`给出1,NA`.当你在NA包含的向量`(1:3)[c(1,2,NA)<2]`上创建逻辑向量时,很容易陷入此状态. (2认同)

Dir*_*tel 13

忘了strptime()和朋友回到POSIXt POSIXlt这里length()总是-九转换为POSIXct帮助:

R> length(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S"))
[1] 9
R> length(as.POSIXct(strptime("2009-10-07 20:21:22", "%Y-%m-%d %H:%M:%S")))
[1] 1
R> 
Run Code Online (Sandbox Code Playgroud)

  • ...它现在在R 2.14.0中返回长度1(也可能是某些早期版本)... (2认同)

Mil*_*der 13

round函数始终舍入到偶数.

> round(3.5)
[1] 4  

> round(4.5)
[1] 4
Run Code Online (Sandbox Code Playgroud)

  • 我很确定这是浮点_gotcha_,而不是R _gotcha_. (3认同)

Tom*_*mmy 12

整数的数学与双打略有不同(有时复杂也很奇怪)

更新他们在R 2.15中修复了一些东西

1^NA      # 1
1L^NA     # NA
(1+0i)^NA # NA 

0L %/% 0L # 0L  (NA from R 2.15)
0 %/% 0   # NaN
4L %/% 0L # 0L  (NA from R 2.15)
4 %/% 0   # Inf
Run Code Online (Sandbox Code Playgroud)


Mar*_*rek 11

我很惊讶没人提这个,但是:

TF可替代,TRUEFALSE没有.

例:

x <- sample(c(0,1,NA), 100, T)
T <- 0:10

mean(x, na.rm=T)
# Warning in if (na.rm) x <- x[!is.na(x)] :
#   the condition has length > 1 and only the first element will be used
# Calls: mean -> mean.default
# [1] NA

plot(rnorm(7), axes=T)
# Warning in if (axes) { :
#   the condition has length > 1 and only the first element will be used
# Calls: plot -> plot.default
# Warning in if (frame.plot) localBox(...) :
#   the condition has length > 1 and only the first element will be used
# Calls: plot -> plot.default
Run Code Online (Sandbox Code Playgroud)

[编辑] ctrf+F欺骗我.谢恩在评论中提到了这一点.


And*_*rew 8

阅读数据可能比您想象的更成问题.今天我发现如果你使用read.csv(),如果.csv文件中的一行为空,read.csv()会自动跳过它.这对大多数应用程序都有意义,但是如果你从几千个文件中自动从(例如)第27行中提取数据,并且前面的一些行可能是空白,也可能不是空白,如果你不小心,事情会变得非常糟糕错误.

我现在用

data1 <- read.table(file_name, blank.lines.skip = F, sep = ",")
Run Code Online (Sandbox Code Playgroud)

当您导入数据时,请检查您是否正在执行您实际认为自己正在做的事情一次又一次......


rle*_*ndi 8

功能的棘手行为all.equal().

我的一个连续错误是比较一组浮点数.我有一个像:

... mu,  tau, ...
... 0.5, 1.7, ...
Run Code Online (Sandbox Code Playgroud)

读取文件并尝试对数据进行子集有时会起作用,有时会失败 - 当然,由于一次又一次地陷入浮点陷阱的凹坑.首先,数据只包含整数值,然后它总是转换为实际值,你知道故事.应该使用all.equal()函数而不是==运算符进行比较,但当然,我第一次编写的代码使用后一种方法.

是的,很酷,但all.equal()返回TRUE相同的数字,但如果失败则会出现文本错误消息:

> all.equal(1,1)
[1] TRUE
> all.equal(1:10, 1:5)
[1] "Numeric: lengths (10, 5) differ"
> all.equal(1:10, c(1:5,1:5))
[1] "Mean relative difference: 0.625"
Run Code Online (Sandbox Code Playgroud)

解决方案是使用isTRUE()功能:

if (!isTRUE(all.equal(x, y, tolerance=doubleErrorRate))) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

我有多少次阅读all.equals()说明...


Kev*_*ght 7

这个伤害太多了,我花了几个小时为bug报告添加评论.我没有实现我的愿望,但至少下一个版本的R会产生错误.

R> nchar(factor(letters))
 [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Run Code Online (Sandbox Code Playgroud)

更新:从R 3.2.0(可能更早)开始,此示例现在生成错误消息.正如下面的评论中提到的,因子不是向量而nchar()需要向量.

R> nchar(factor(letters))
Error in nchar(factor(letters)) : 'nchar()' requires a character vector
R> is.vector(factor(letters))
[1] FALSE
Run Code Online (Sandbox Code Playgroud)

  • 我学到的是一个因子是_not_一个向量,'nchar'只适用于向量. (2认同)

小智 6

  1. 忘记包含空括号,意外地列出了函数的源代码:例如"ls"与"ls()"

  2. true和false不要将它剪切为预定义的常量,如Matlab,C++,Java,Python; 必须使用TRUE&FALSE

  3. 不可见的返回值:例如".packages()"不返回任何内容,而"(.packages())"返回包基名称的字符向量

  • 嗯,这些并不完全相同.您可以覆盖T,但设置为TRUE.请尝试以下方法确认:{T < - FALSE; T}.非常危险!所以,Stuart是对的:你需要小心你的真/假值. (10认同)

rcs*_*rcs 5

例如,数字3.14是数字常量,但表达式+3.14和-3.14是对函数的调用,+并且-:

> class(quote(3.14))
[1] "numeric"
> class(quote(+3.14))
[1] "call"
> class(quote(-3.14))
[1] "call"
Run Code Online (Sandbox Code Playgroud)

请参阅John Chambers的" 软件数据分析 - 使用R编程"中的第13.2节


Tom*_*mmy 5

$运算符中的部分匹配:这适用于列表,但也适用于data.frame

df1 <- data.frame(foo=1:10, foobar=10:1)
df2 <- data.frame(foobar=10:1)

df1$foo # Correctly gets the foo column
df2$foo # Expect NULL, but this returns the foobar column!!!

# So, should use double bracket instead:
df1[["foo"]]
df2[["foo"]]
Run Code Online (Sandbox Code Playgroud)

[[运营商也有一个exact标志,但令人欣慰的是TRUE默认.

部分匹配也会影响attr:

x1 <- structure(1, foo=1:10, foobar=10:1)
x2 <- structure(2, foobar=10:1)

attr(x1, "foo") # Correctly gets the foo attribute
attr(x2, "foo") # Expect NULL, but this returns the foobar attribute!!!

# So, should use exact=TRUE
attr(x1, "foo", exact=TRUE)
attr(x2, "foo", exact=TRUE)
Run Code Online (Sandbox Code Playgroud)


use*_*293 5

自动重复用作索引的向量(“回收” ):

R> all.numbers <- c(1:5)
R> all.numbers
[1] 1 2 3 4 5
R> good.idxs <- c(T,F,T)
R> #note unfortunate length mismatch
R> good.numbers <- all.numbers[good.idxs]
R> good.numbers
[1] 1 3 4
R> #wtf? 
R> #why would you repeat the vector used as an index 
R> #without even a warning?
Run Code Online (Sandbox Code Playgroud)

  • 这种向量回收在 R 中很常见。我觉得这是一种喜忧参半的现象,也是意外行为的潜在来源。 (2认同)

Kev*_*ght 5

零长度向量有一些怪癖:

R> kk=vector(mode="numeric",length=0)
R> kk
numeric(0)
R> sum(kk)
[1] 0
R> var(kk)
[1] NA
Run Code Online (Sandbox Code Playgroud)