8

事实证明,在 gtable 中使用unit.pmax默认的宽度/高度比较比我希望的要难;经过几个小时的挠头后,我将其范围缩小到这种情况:

library(grid)

w <- list(unit(1,"null"), unit(1,"null"))
class(w) <-  c("unit.list", "unit")
h <- unit(1, "in")
gl1 <- grid.layout(1, 2, widths = w, heights = h,
                   respect = TRUE)
grid.newpage()
grid.show.layout(gl1) # fine

w2 <- w
w2[[1]] <- unit.pmax(unit(1,"null"), unit(1,"null"))
gl2 <- grid.layout(1, 2, widths = w2, heights = h,
                   respect = FALSE)
grid.newpage()
grid.show.layout(gl2)# fine

gl3 <- grid.layout(1, 2, widths = w2, heights = h,
                   respect = TRUE)
grid.newpage()
grid.show.layout(gl3)

## Error in grid.Call.graphics(L_setviewport, vp, TRUE) : 
##  non-finite location and/or size for viewport

所以 和 的结合unit.pmax(unit(1,"null"), unit(1,"null"))使respect = TRUE网格抱怨。如果您想知道,这种情况会出现在 ggplot2 中facet_gridtheme(aspect.ratio = ...).

unit.pmax()在尝试使用参数之前,我可以模糊地想象应该简化空单位respect,但我真的不知道这一切意味着什么。但在实践中,它阻止了我改进 gtable 的 cbind/rbind。

任何解决方法?

编辑:我不知道如何提供一个最小的例子ggplot2,除了安装我的叉子和运行

ggplot(data.frame(x=1:8, y=1:8, f=gl(2,4)), aes(x, y)) + 
  geom_point() +  
  facet_grid(f~.) + 
  theme(aspect.ratio=3)
# Error in grid.Call.graphics(L_setviewport, vp, TRUE) : 
#  non-finite location and/or size for viewport

所以unit.pmax()在这种情况下会失败,而当前的比较方法compare.unit(,,pmax)在其他情况下会失败,例如,

p1 = qplot(1, 1); p2 = qplot(1,1)
cbind(ggplotGrob(p1), ggplotGrob(p2), size="max")
# Error in mmm < each : comparison of these types is not implemented
4

2 回答 2

3

这不是最佳的,但如果所有其他方法都失败了,您可以重写unit.pmax以使其按照您希望的方式执行。

以下函数的作用与此类似unit.pmax(),只是当它被要求找到两个或多个单位对象的最大值时,都以单位为"null"单位,它返回它们的“最大”值,而不是形式的表达式max(x,y,...)。(有关示例,请参见下面的第二个代码块。)

unit.pmax2 <- 
function (...) 
{
    select.i <- function(unit, i) {
        unit[i, top = FALSE]
    }
    x <- list(...)
    numargs <- length(x)
    if (numargs == 0L) 
        stop("no arguments where at least one expected")
    maxlength <- 0L
    for (i in seq_len(numargs)) if (length(x[[i]]) > maxlength) 
        maxlength <- length(x[[i]])        
    ## result <- max(unit.list.from.list(lapply(x, select.i, 1L)))
    UL <- grid:::unit.list.from.list(lapply(x, select.i, 1L))                 ##
    result <- if(all(sapply(UL, attr, "unit")=="null")) {                     ##
                  UL[which.max(UL)]} else {max(UL)}                           ##
    if (maxlength > 1L) 
        for (i in 2L:maxlength) {
            ## result <- unit.c(result, max(unit.list.from.list(lapply(x, 
            ##             select.i, i))))
            UL <- grid:::unit.list.from.list(lapply(x, select.i, i))          ##
            temp <- if(all(sapply(UL, attr, "unit")=="null")) {               ##
                        UL[which.max(UL)]} else {max(UL)}                     ##
            result <- unit.c(result, temp)                                    ##
        }
    result
}

要查看 和 之间的区别unit.pmax(),请unit.pmax2()比较:

A <- list(unit(1,"null"), unit(1,"null"), unit(1,"null"))
B <- list(unit(1,"null"), unit(4,"null"), unit(1,"null"))
C <- list(unit(1,"null"), unit(2,"null"), unit(1,"inch"))

class(A) <- class(B) <- class(C) <- c("unit.list", "unit")

unit.pmax(A, B, C)
# [1] max(1null, 1null, 1null) max(1null, 4null, 2null) max(1null, 1null, 1inch)    
unit.pmax2(A, B, C)
# [1] 1null                    4null                    max(1null, 1null, 1inch)

测试它表明它有效。(请注意,您还需要替换w2[[1]] <- ...w2[1] <- ...以避免投诉时respect = TRUE。)

library(grid)

w2 <- list(unit(1,"null"), unit(1,"null"))
class(w2) <-  c("unit.list", "unit")
h <- unit(1, "in")

w2[1] <- unit.pmax2(unit(1,"null"), unit(1,"null"))
## w2[[1]] <- unit.pmax(unit(1,"null"), unit(1,"null"))  ## For comparison
gl3 <- grid.layout(1, 2, widths = w2, heights = h,
                   respect = TRUE)
grid.newpage()
grid.show.layout(gl3)

在此处输入图像描述

于 2014-06-02T16:46:56.480 回答
3

Paul Murrell 在 R-devel @r65845中的修复似乎解决了这个问题。不幸的是,这意味着更新gtable必须至少等到下一个 R 版本(并且可能更长,因为 ggplot2 dev 通常对支持旧版本采取保守的方法)。

于 2014-06-04T13:51:13.433 回答