获取ggplot2中的绘图区域宽度

时间:2012-12-13 19:49:40

标签: r ggplot2

有没有办法在网格窗口中获得绘图区域的宽度?例如,如果更改plot.margin或者y轴标签的font-size增加,它会增大或缩小。是隐藏在str(p)的某个地方吗?

任何尺寸的尺寸都可行。我需要能够在不同情况下测量绘图区域宽度的相对变化,例如更改y轴标签的字体大小。

enter image description here

df = data.frame(x = (1:3),One=c(12, 8, 13),Two=c(13, 7, 11),Three=c(11, 9, 11))
df.melt = melt(df, id.vars="x")

p = ggplot(df.melt, aes(x=x, y=value, color=variable)) + 
  geom_line() +
  coord_cartesian(xlim=c(min(df.melt$x),max(df.melt$x))) +
  theme(legend.position="none", plot.margin = unit(c(1, 4, 1, 1), "cm")) 
p

更新 - 澄清:请帮我计算a/b

enter image description here

p = ggplot(df.melt, aes(x=x, y=value, color=variable)) + 
  geom_line() + coord_cartesian(xlim=c(min(df.melt$x),max(df.melt$x))) +
  theme(legend.position="none")

p1 = p + theme(plot.margin=unit(c(1,1,1,1),"cm"), axis.text.y=element_text(size=10))
p2 = p + theme(plot.margin=unit(c(1,1,1,2),"cm"), axis.text.y=element_text(size=30))
grid.arrange(p1, p2, ncol=2)

3 个答案:

答案 0 :(得分:15)

ggplot2中的图使用网格图形。已生成的图形场景 使用网格图形包由grobs和视口组成。

您可以使用 gridDebug 包来检查grob。

  1. showGrob显示用于绘制场景的凹凸的位置和名称

          showGrob()
    
  2. 获取grob的gpath

      sceneListing <- grid.ls(viewports=T, print=FALSE)
      do.call("cbind", sceneListing)
    
       name                                gPath                                                      
    [1,] "ROOT"                              ""                                                         
    [2,] "GRID.gTableParent.45019"           ""                                                         
    [3,] "background.1-5-6-1"                "GRID.gTableParent.45019"                                  
    [4,] "spacer.4-3-4-3"                    "GRID.gTableParent.45019"                                  
    [5,] "panel.3-4-3-4"                     "GRID.gTableParent.45019"                                  
    [6,] "grill.gTree.44997"                 "GRID.gTableParent.45019::panel.3-4-3-4"                   
    
  3. 检索gorb

    h <- grid.get(gPath="GRID.gTableParent.45019")
    
  4. 获取h属性(例如)

    h$layoutvp$width
    
  5. 应用:

    grid.get('x',grep=TRUE,global=T)
    (polyline[panel.grid.minor.x.polyline.21899], polyline[panel.grid.major.x.polyline.21903], gTableChild[axis-l.3-3-3-3], gTableChild[axis-b.4-4-4-4], gTableChild[xlab.5-4-5-4]) 
    >  grid.get('x',grep=TRUE,global=T)[[3]]
    gTableChild[axis-l.3-3-3-3] 
    >  xx <- grid.get('x',grep=TRUE,global=T)[[3]]
    > grobWidth(xx)
    [1] sum(1grobwidth, 0.15cm+0.1cm)
    

答案 1 :(得分:9)

这让我很感兴趣,可以更深入地研究它。我希望grid.ls函数能够提供导航到正确视口的信息来获取信息,但是对于你的例子,有一些步骤被'...'取代而我不能看看如何改变它以提供易于使用的东西。但是,使用grid.ls或其他工具,您可以看到不同视口的名称。对于您的示例,感兴趣的视口都命名为“panel.3-4-3-4”,下面是一些导航到1st的代码,找到以英寸为单位的宽度,导航到第二个并找到那个的宽度以英寸为单位。

grid.ls(view=TRUE,grob=FALSE)
current.vpTree()
seekViewport('panel.3-4-3-4')
a <- convertWidth(unit(1,'npc'), 'inch', TRUE)
popViewport(1)
seekViewport('panel.3-4-3-4')
b <- convertWidth(unit(1,'npc'), 'inch', TRUE)
a/b

我无法找到一个简单的方法来到第二个面板而不弹出第一个面板。这很有用,并且提供了所需的信息,遗憾的是,由于它从列表中弹出第一个面板,您无法返回到它并查找其他信息或进行修改。但这确实可以提供您要求的信息,可以在以后的图表中使用。

也许其他人知道如何导航到第二个面板而不弹出第一个面板,或者让每个面板的完整vpPath直接导航。

答案 2 :(得分:5)

这个答案主要是回复@java_xof的评论。回复太长,包含代码,因此不适合评论。但是,它也可以帮助解决原始问题(或至少给出一个起点)。

这是一个函数和一些使用它的代码(它需要tcltk和tkrplot包):

library(ggplot2)
library(tkrplot)
TkPlotLocations <- function(FUN) {
    require(tkrplot)

    cl <- substitute(FUN)
    replot <- function() eval(cl)

    tt <- tktoplevel()
    img <- tkrplot(tt, replot, vscale=1.5, hscale=1.5)
    tkpack(img)

    tkpack(xfr <- tkframe(tt), side='left')
    tkpack(yfr <- tkframe(tt), side='left')

    xndc <- tclVar()
    yndc <- tclVar()
    xin <- tclVar()
    yin <- tclVar()

    tkgrid(tklabel(xfr, text='x ndc'), tklabel(xfr, textvariable=xndc))
    tkgrid(tklabel(yfr, text='y ndc'), tklabel(yfr, textvariable=yndc))
    tkgrid(tklabel(xfr, text='x inch'), tklabel(xfr, textvariable=xin))
    tkgrid(tklabel(yfr, text='y inch'), tklabel(yfr, textvariable=yin))

    iw <- as.numeric(tcl("image","width", tkcget(img, "-image")))
    ih <- as.numeric(tcl("image","height",tkcget(img, "-image")))

    cc <- function(x,y) {
        x <- (as.real(x)-1)/iw
        y <- 1-(as.real(y)-1)/ih
        c(x,y)
    }

    mm <- function(x, y) {
        xy <- cc(x,y)
        tclvalue(xndc) <- xy[1]
        tclvalue(yndc) <- xy[2]
        tclvalue(xin) <- grconvertX(xy[1], from='ndc', to='inches')
        tclvalue(yin) <- grconvertY(xy[2], from='ndc', to='inches')
    }

    tkbind( img, "<Motion>", mm)

    invisible()
}


x <- runif(25)
y <- rnorm(25, x, 0.25)
plot(x,y)
par()$pin
par()$plt
TkPlotLocations(plot(x,y))
qplot(x,y)
par()$pin
par()$plt
TkPlotLocations(print(qplot(x,y)))
qplot(x,y) + xlab('Multi\nline\nx\nlabel')
par()$pin
par()$plt
TkPlotLocations(print(qplot(x,y) + xlab('Multi\nline\nx\nlabel')))

定义上述函数,然后运行以下行将生成3个相同随机数据的图。您可以看到par()$pinpar()$plt(以及其他参数)的结果对于3个绘图完全相同,即使绘图区域在图中有所不同。

还会有3个新窗口弹出,在窗口中你可以将鼠标指针移动到图形上,在窗口底部你会看到指针在标准化设备坐标和英寸中的当前位置(均来自设备区域的左下角)。您可以将鼠标指针悬停在图形(或任何其他部分)的角上,以查看值并在3个图形之间进行比较。

这可能足以回答原始问题的至少一部分(只是不以编程方式,这将更有用)。可以修改功能以打印出其他测量值。如果其他人感兴趣,我可以扩展这个并将其包含在未来的包中。