r - 估计ggplot2中图例占用的绘图百分比

标签 r ggplot2 r-grid grob

我有一些 ggplot 功能,但我想给用户一个警告,以防他们严重滥用它。问题是这样的:如果有很多组并且组名很长,那么图例就会变得很大,占据了整个情节:

example of problem

但如果我要更改情节名称,我会得到:

okayish

我所拥有的是:

  • ggplot/ggbuild 对象
  • 绘图窗口的尺寸(默认为 480 x 320),但可以更改。

  • 我想用这些来估计图例占用的总面积(所以如果图例大小/绘图大小的比例太大,我可以发出警告)。这是我用来创建数字的一些示例代码:
    library(ggplot2)
    
    # stolen from https://ryouready.wordpress.com/2008/12/18/generate-random-string-name/
    MHmakeRandomString <- function(n=1, lenght=12) {
        randomString <- c(1:n)                  
        for (i in 1:n)
        {
            randomString[i] <- paste(sample(c(0:9, letters, LETTERS),
                                            lenght, replace=TRUE),
                                     collapse="")
        }
        return(randomString)
    }
    
    makeData <- function(k, useLongNames = FALSE) {
    
        x <- c(1, 100)
        X <- cbind(1, x)
        b <- matrix(rnorm(2*k), k, 2)
    
        y <- numeric(2*k)
        for (i in seq_len(k))
            y[1:2 + 2*(i-1)] <- X %*% b[i, ]
    
        df <- data.frame(x = c(1, n), y = y)
    
        if (useLongNames) {
            df$g <- factor(rep(MHmakeRandomString(k), each = 2))
        } else {
            df$g <- factor(rep(1:k, each = 2))
        }
    
        return(df)
    
    }
    
    # okayish plot
    df <- makeData(50)
    g0 <- ggplot(data = df, aes(x = x, y = y, group = g, color = g)) +
        geom_line() + 
        guides(color=guide_legend(nrow=5)) 
    
    # unreadable plot    
    df <- makeData(50, useLongNames = TRUE)
    g1 <- ggplot(data = df, aes(x = x, y = y, group = g, color = g)) +
        geom_line() + 
        guides(color=guide_legend(nrow=5))
    
    # to plot
    # x11(width = 480, height = 320)
    # print(g0)
    # x11(width = 480, height = 320)
    # print(g1)
    

    我认为答案在 ggplotGrob() 中的某个地方.但是,我不熟悉 grobs(并且找不到明确的文档)并陷入困境
    gGrob0 <- ggplotGrob(g0)
    gGrob1 <- ggplotGrob(g1)
    gGrob0$grobs[[15]]$grobs[[1]]$grobs # all legend elements
    
    convertWidth(grobWidth(gGrob0$grobs[[15]]), unitTo = "inches") # 4.5128 inches
    convertWidth(grobWidth(gGrob1$grobs[[15]]), unitTo = "inches") # 12.419 inches
    # but this is not correct:
    # number of legend columns x legend width <= plot width
    # 10 * 12.419 <= 480
    

    这似乎给了我很多关于我感兴趣的东西的信息。如何将这些信息转换为图例将占用的总宽度?提前谢谢了。

    最佳答案

    这是我的解决方案(受 m-dz 评论的启发)。对象 g0g1来自问题中的代码。

    plotAndPrintRatio <- function(g, width, height) {
    
        gGrob <- ggplotGrob(g)
        tmpfile <- tempfile(pattern = "png")
        png(tmpfile, width = width, height = height) # it is necessary to open a device
        plot(g)
        legendSize <- as.numeric(convertWidth(grobWidth(gGrob$grobs[[15]]), unitTo = "inches"))
        plotSize <-   as.numeric(convertWidth(grobWidth(gGrob$grobs[[7]]), unitTo = "inches"))
        print(legendSize / plotSize) # the ratio of legend size to plot size
        dev.off()
    
        return(tmpfile)
    }
    
    # problem only in the first plot
    f1 <- plotAndPrintRatio(g0, width = 480, height = 320) # 0.6769345
    f2 <- plotAndPrintRatio(g1, width = 480, height = 320) # 1.887872 --> too big!
    
    # larger window size fixes the problem
    f3 <- plotAndPrintRatio(g0, width = 1200, height = 900) # 0.2707738
    f4 <- plotAndPrintRatio(g1, width = 1200, height = 900) # 0.7551488
    filesList <- list(f1, f2, f3, f4)
    
    # to show the saved pngs:
    dev.off() # might be needed to clean up the plotting window
    grid::grid.raster(png::readPNG(f1))
    grid::grid.raster(png::readPNG(f2))
    grid::grid.raster(png::readPNG(f3))
    grid::grid.raster(png::readPNG(f4))
    
    # to remove the tempfiles created:
    # lapply(filesList, file.remove)
    

    关于r - 估计ggplot2中图例占用的绘图百分比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45794157/

    相关文章:

    r - grid : How to specify limits to avoid grid. 点()绘制超出视口(viewport)?

    r - 如何从 shell 脚本运行 knitr

    r - 如何在具有facets的组中添加一条最适合ggplot的线

    从 R 中的矩阵中删除无限值

    r - 使用ggsave时遇到 "Error: $ operator is invalid for atomic vectors"

    R - ggplot 上的背景颜色沿对角线分割?

    r - 使用网格填充在 R 中绘制的贝塞尔曲线

    r - 向维恩图添加图例

    r - 获取每一行中给定值的列名

    无法使用请求的 python 版本,因为另一个版本已在 Shiny 的应用程序中初始化