网格单元向量中的元素替换

element replacement in grid unit vector

我已经被这个问题困扰过好几次了,所以这里有一个编造的问题,供其他可能偶然发现同样问题的人使用。

考虑这个网格单位向量,

a = unit(1:3, c("cm", "in", "npc"))

我想用新值替换一些元素。自然的方法是,

a[1] = unit(2,"pt")
a
# [1] 2cm  2in  3npc

出了点问题:只更改了数值,没有更改单位。为什么?怎么办?

编辑: 正如下面的一个答案所指出的,这些单位只是具有属性的数字向量。然而,他们的后代 unit.arithmeticunit.list 也应该被认为是完全通用的解决方案(例如用于调整 ggplot 对象的面板大小)。考虑这个单位向量,

(b = a + unit(1, "npc"))
# [1] 1cm+1npc  2in+1npc  3npc+1npc
# [1] "unit.arithmetic" "unit"   

现在替换特定元素更加棘手,因为它们不再是原子的。

看起来 a 只是一个附加了一些属性的原子向量。因此,当您使用 a[1] = unit(2,"pt") 时,新的 unit 函数会创建另一个长度为 1 的原子向量来替换 a[1] 的值。属性保持不变。

所以,这样的事情似乎有效:

a[1] <- 2
attr(a, 'unit')[1] <- 'pt'

> a
[1] 2pt  2in  3npc

在与 Paul Murrell 讨论之后(有趣的是,重新发明了我想要 的东西),问题在于缺少网格单元的 [<- 方法。长期的解决方法是实施这些方法,但这并非微不足道,因为网格单元带有 unit.arithmetic 和 unit.list 等兄弟单元,并且它们的交互可能变得难以理解。

更简单、面向用户的修复方法是将此类单位向量转换为 unit.list 对象,这将更像常规 R 列表一样继承访问器方法。可以使用未导出的函数 grid:::unit.list().

完成对 unit.list 对象的提升
a = unit(1:3, c("cm", "in", "npc"))
b = grid:::unit.list(a)
is.list(b) # check that indeed this is a list object, thanks @Josh O'Brien
# [1] TRUE
# so now we can use standard list methods
b[[1]] = unit(2,"pt")
b
#[1] 2pt  2in  3npc

grid now has a [<-.unit method.