grid.layout不喜欢尊重和复合单位

时间:2014-06-01 20:41:23

标签: r ggplot2 r-grid gtable

使用unit.pmax作为gtable中宽度/高度的默认比较,证明比我希望的更难;经过几个小时的搔痒,我把它缩小到这种情况:

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提供最小示例,而不是安装my fork并运行

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

2 个答案:

答案 0 :(得分:3)

它不是最佳的,但如果所有其他方法都失败了,您可以重写unit.pmax以使其按照您的意愿行事。

以下函数的行为与unit.pmax()类似,只是当它被要求查找两个或更多单位对象的最大值时,全部以"null"为单位,它返回它们的值&#34;最大&#34;一,而不是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)

enter image description here

答案 1 :(得分:3)

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