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

问题描述 投票:57回答:25

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

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

r r-faq
25个回答
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

那么这里发生的是:

  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应该提供一个唯一的行名。

12
投票

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

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

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> 

11
投票

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

round> round(3.5) [1] 4 > round(4.5) [1] 4 可以覆盖,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 T不会。

例:

F

[编辑] TRUE欺骗我。 FALSE


8
投票

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

我现在用

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

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


8
投票

ctrf+F函数的棘手行为。

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

Shane mention about this in his comment

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

是的,很酷,但... mu, tau, ... ... 0.5, 1.7, ... 返回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" 描述......


7
投票

这个伤害太多了,我花了几个小时给isTRUE()添加评论。我没有实现我的愿望,但至少R的下一个版本会产生错误。

if (!isTRUE(all.equal(x, y, tolerance=doubleErrorRate))) {
    ...
}

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

all.equals()

6
投票
  1. 忘记包括空括号,意外地列出了函数的源代码:例如“ls”与“ls()”
  2. true和false不要将它剪切为预定义的常量,如Matlab,C ++,Java,Python;必须使用TRUE&FALSE
  3. 不可见的返回值:例如“.packages()”不返回任何内容,而“(.packages())”返回包基本名称的字符向量

5
投票

例如,数字3.14是一个数值常数,但表达式+3.14和-3.14是对函数bug-reportR> 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 的调用:

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

请参阅约翰钱伯斯的书中的第13.2节+


5
投票

零长度向量有一些怪癖:

-

5
投票

> class(quote(3.14)) [1] "numeric" > class(quote(+3.14)) [1] "call" > class(quote(-3.14)) [1] "call" 运算符中的部分匹配:这适用于列表,但也适用于Software for Data Analysis - Programming with R

R> kk=vector(mode="numeric",length=0)
R> kk
numeric(0)
R> sum(kk)
[1] 0
R> var(kk)
[1] NA

$运算符也有一个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"]] 默认情况下。

部分匹配也会影响[[

exact

4
投票

使用列表,有几个不直观的事情:

当然,TRUEattr之间的区别需要一些时间来适应。对于列表,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) 返回(可能是1个)元素的列表,而[返回列表中的元素。

列表创建:

[[

那么,如何将NULL插入列表?

[

最后一些高级的东西,如通过嵌套列表索引:

[[

42
投票

[哈德利指出in a comment。]

当使用序列作为迭代的索引时,最好使用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

现在制作矢量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

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

> for(i in 1:length(x)) print(i)
[1] 1
[1] 0
> for(i in seq_along(x)) print(i)
>

4
投票

R中最大的困惑之一是# When you're used to this: x <- numeric(5) # A vector of length 5 with zeroes # ... this might surprise you x <- list(5) # A list with a SINGLE element: the value 5 # This is what you have to do instead: x <- vector('list', 5) # A vector of length 5 with NULLS 确实会降低因子水平,但x <- list("foo", 1:3, letters, LETTERS) # A sample list x[[2]] <- 1:5 # Put 1:5 in the second element # The obvious way doesn't work: x[[2]] <- NULL # This DELETES the second element! # This doesn't work either: x[2] <- NULL # This DELETES the second element! # The solution is NOT very intuitive: x[2] <- list(NULL) # Put NULL in the second element # Btw, now that we think we know how to delete an element: x <- 1:10 x[[2]] <- NULL # Nope, gives an ERROR! x <- x[-2] # This is the only way for atomic vectors (works for lists too) 却没有!

x <- list(a=1:3, b=list(c=42, d=13, e="HELLO"), f='bar')
x[[c(2,3)]] # HELLO (first selects second element and then it's third element)
x[c(2,3)]   # The second and third elements (b and f)

有关更多信息,请参阅:[i, drop = TRUE]


4
投票

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

[i, j, drop = TRUE]

3
投票

来自编译语言和Matlab,我偶尔会对函数式语言中函数的一个基本方面感到困惑:它们必须在使用之前进行定义!仅仅让他们被R解释器解析是不够的。当您使用嵌套函数时,这主要是它的头部。

在Matlab中你可以做到:

> df = data.frame(a = c("europe", "asia", "oceania"), b = c(1, 2, 3))
> df$a[1:2, drop = TRUE]
[1] europe asia  
Levels: asia europe          <---- drops factor levels, works fine
> df[1:2,, drop = TRUE]$a
[1] europe asia  
Levels: asia europe oceania  <---- does not drops factor levels!

如果您尝试在R中执行相同的操作,则必须先放置嵌套函数,否则会出错!仅仅因为你已经定义了这个函数,它就不会在命名空间中被分配给变量了!另一方面,该函数可以引用尚未定义的变量。

drop = TRUE doesn't drop factor levels in data.frame while in vector it does

3
投票

从今天开始:qnorm()获取概率,而pnorm()获取Quantiles。


3
投票

对我来说,这是一种反直觉的方式,当你使用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? 将data.frame导出到文本文件时,然后要导入它,你需要添加一个额外的参数来获得完全相同的data.frame,如下所示:

function f1()
  v1 = 1;
  v2 = f2();
  fprintf('2 == %d\n', v2);

  function r1 = f2()
    r1 = v1 + 1 % nested function scope
  end
end

我还在SO中发布了f1 <- function() { f2 <- function() { v1 + 1 } v1 <- 1 v2 = f2() print(sprintf("2 == %d", v2)) } ,并被@BenBolker建议作为这个Q的答案。


1
投票

write.csv函数集不仅适用于矩阵,而且适用于多维数组。在我的研究中,我经常有一个数据集,例如大气温度。它存储在尺寸为write.csv(m, file = 'm.csv') read.csv('m.csv', row.names = 1) # Note the row.names argument 的多维数组中,从现在开始称为this question。一个样机示例是:

apply

使用x,y,level,time可以轻松获得:

multi_dim_array

这使得multi_dim_array = array(runif(96 * 48 * 6 * 100, -50, 50), dim = c(96, 48, 6, 100)) > str(multi_dim_array) # x y lev time num [1:96, 1:48, 1:6, 1:100] 42.4 16 32.3 49.5 24.9 ... apply的论证似乎不那么反直觉了。我首先,为什么不使用“row”和“col”而不是1和2.但事实上它也适用于具有更多尺寸的数组,这清楚地表明为什么使用像这样的# temporal mean value > str(apply(multi_dim_array, 4, mean)) num [1:100] -0.0113 -0.0329 -0.3424 -0.3595 -0.0801 ... # temporal mean value per gridcell (x,y location) > str(apply(multi_dim_array, c(1,2), mean)) num [1:96, 1:48] -1.506 0.4553 -1.7951 0.0703 0.2915 ... # temporal mean value per gridcell and level (x,y location, level) > str(apply(multi_dim_array, c(1,2,3), mean)) num [1:96, 1:48, 1:6] -3.839 -3.672 0.131 -1.024 -2.143 ... # Spatial mean per level > str(apply(multi_dim_array, c(3,4), mean)) num [1:6, 1:100] -0.4436 -0.3026 -0.3158 0.0902 0.2438 ... 是首选。


35
投票

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

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


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> 

23
投票

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

x <- 10.2 * 100
x
1020
as.integer(x)
1019

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


20
投票

允许qazxsw poi,qazxsw poi和qazxsw poi的组合可能很烦人。它们的行为不同,对其中一个的测试不一定适用于其他人:

NA

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

NaN

18
投票

总是测试当你有Inf时会发生什么!

我经常需要注意的一件事(在经历了许多痛苦的经历之后)是> 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 的价值观。 R函数易于使用,但没有任何编程方式可以克服数据问题。

例如,任何使用> is.finite(x) [1] FALSE FALSE FALSE 的净矢量运算都等于NA。从表面上看,这是“令人惊讶的”:

NA

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

换句话说,缺省值通常与默认情况下的测量值一样重要。许多函数都有NA默认值;值得花一些时间来决定如何解释这些默认设置。

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

> x <- c(1,1,2,NA)
> 1 + NA
[1] NA
> sum(x)
[1] NA
> mean(x)
[1] NA

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

na.rm=TRUE/FALSE

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


13
投票

忘记NA和朋友返回> TRUE && NA [1] NA > FALSE && NA [1] FALSE > TRUE || NA [1] TRUE > FALSE || NA [1] NA 总是九的> any(c(TRUE, NA)) [1] TRUE > any(c(FALSE, NA)) [1] NA > all(c(TRUE, NA)) [1] NA - 转换为strptime()有助于:

POSIXt POSIXlt

13
投票

length()函数总是舍入到偶数。

POSIXct
© www.soinside.com 2019 - 2024. All rights reserved.