我在问题的答案中看到+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
做什么的其他方法是什么?答案 0 :(得分:15)
x + 0L
是x
上的元素明智操作;因此,它通常保留数据的形状。 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
)