用于布尔值的as.integer()和+ 0L有什么区别?

时间:2015-02-09 14:29:17

标签: r

我在问题的答案中看到+0L,发现它适用于矩阵/数据框/数据表,其中as.integer()无法保留初始数据类。

> a <- matrix(TRUE, nrow=3, ncol=3)
> a
     [,1] [,2] [,3]
[1,] TRUE TRUE TRUE
[2,] TRUE TRUE TRUE
[3,] TRUE TRUE TRUE
> as.integer(a)
[1] 1 1 1 1 1 1 1 1 1
> a+0L
     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    1    1    1
[3,]    1    1    1
  • 这些方法之间是否存在其他差异?
  • 使用其中一种时有哪些优点和缺点?

[编辑:]评论中有很多智慧!显然有很多不同的方法可以达到相同的结果,其中一些我不知道,所以:

  • 实现a+0L做什么的其他方法是什么?

3 个答案:

答案 0 :(得分:15)

x + 0Lx上的元素明智操作;因此,它通常保留数据的形状。 as.integer不是:它需要整个结构 - 这里是一个矩阵 - 并将其转换为一维整数向量。

那就是说,在一般情况下,我强烈建议使用as.integer并阻止+ 0L作为一个聪明的黑客(记住:经常,聪明≠好)。如果你想保留数据的形状我建议在评论中使用David的方法,而不是+ 0L hack:

a[] = as.integer(a)

这使用as.integer的正常含义,但结果会分配给 a 的各个元素,而不是a本身。换句话说,a的形状保持不变。

答案 1 :(得分:11)

0L中所述,将a提升为?Arithmetic整数:

  

逻辑向量将被强制转换为整数或数字向量,为FALSE   值为零,TRUE值为1。

因此,使用a的任何算术运算和该操作的标识元素(但不必在某个时刻转到数字,例如/^ )会工作:

a+0L
a-0L
a*1L
a%/%1
一般的操作也会起作用,所以也许最好的&#34;代码高尔夫版本是:

--a

这与使用!!a将数字对象转换为逻辑的常见技巧并行。

identical(a+0L, a-0L, a*1L, a%/%1L, --a)
[1] TRUE

转换回逻辑:

identical(a, !!--a)
[1] TRUE

一种替代的,也许更清晰的方法是直接更改storage.mode的{​​{1}}:

a

答案 2 :(得分:4)

(这个答案不会增加已经存在的替代品,但我只是为了整理这个帖子中的评论而发帖。)

as.integer按照定义,行为类似于as.vector,即它会删除所有属性(&#34; dim&#34;包括在内)以创建R向量。它不会因为更改typeof而返回同一个对象。要在强制执行后恢复属性,需要显式调用"dim<-""names<-""class<-"等,或者通过存储其参数属性的函数(例如"[<-")调用。例如。 "dim<-"(as.integer(a), dim(a))array(as.integer(a), dim(a))a[] <- as.integer(a)。基准:

x = matrix(T, 1e3, 1e3)
microbenchmark::microbenchmark("dim<-"(as.integer(x), dim(x)),
                               array(as.integer(x), dim(x)), 
                               { x[] = as.integer(x) }, times = 25)
#Unit: milliseconds
#                           expr      min       lq   median        uq      max neval
# `dim<-`(as.integer(x), dim(x)) 1.650232 1.691296 2.492748  4.237985  5.67872    25
#   array(as.integer(x), dim(x)) 6.226130 6.638513 8.526779  8.973268 47.50351    25
#    {     x[] = as.integer(x) } 7.822421 8.071243 9.658487 10.408435 11.90798    25

在上文中,"dim<-" justs为创建的as.integer(x)添加了一个属性,array分配了一个新的向量来存储创建的as.integer(x)"[<-"变化&#34; x&#34;这样它就可以接受创建的as.integer(x)的值,然后迭代通过&#34; x&#34;插入新值。

"[<-"方法有一个缺点:

x = as.character(1:5)
x
#[1] "1" "2" "3" "4" "5"
x[] = as.integer(x)
x
#[1] "1" "2" "3" "4" "5"

或者:

x = 1:5
x
#[1] 1 2 3 4 5
x[] = as.logical(x)
x
#[1] 1 1 1 1 1

可是:

x = round(runif(5), 2)
x
#[1] 0.68 0.54 0.02 0.14 0.08
x[] = as.character(x)
x
#[1] "0.68" "0.54" "0.02" "0.14" "0.08"

即。如果替换对象的"[<-"更高,则typeof无法更改可替换对象的typeof子分配(即"[<-")强制要替换的对象替换对象 none,具体取决于他们的{{1} } s(由SubassignTypeFix完成)。 @Josh O&#39; Brien指出,如果指数缺失,typeof的行为可能存在差异。说实话,在这种情况下我找不到具体的处理方法,例如间接处理缺失的do_subset_dflt"[<-")。

如前所述,还有"["来更改对象的"storage.mode<-"

typeof

效率与"storage.mode<-"(as.character(1:5), "integer") #[1] 1 2 3 4 5 "storage.mode<-"(1:5, "logical") #[1] TRUE TRUE TRUE TRUE TRUE "storage.mode<-"(round(runif(5), 2), "character") #[1] "0.09" "0.38" "0.98" "0.73" "0.81" x = matrix(T, 1e3, 1e3) microbenchmark::microbenchmark("storage.mode<-"(x, "integer"), "dim<-"(as.integer(x), dim(x)), times = 25) #Unit: milliseconds # expr min lq median uq max neval # `storage.mode<-`(x, "integer") 1.986055 2.01842 2.147181 2.406096 6.019415 25 # `dim<-`(as.integer(x), dim(x)) 1.984664 2.02016 2.111684 2.613854 6.174973 25 类似,因为它们都强制一次并存储属性。

二元操作(正如詹姆斯和康拉德鲁道夫所提到的)强制他们的论点适合"dim<-"并保留属性(&#34; dim&#34;,&#34;名称&#34;,&#34; class&#34; etc.)取决于有关这两个参数的规则。 (Section&#34; Value&#34; in typeof