【问题标题】:Control ggplot2 facet height independently from number of row facets独立于行分面数控制 ggplot2 分面高度
【发布时间】:2013-09-12 01:33:15
【问题描述】:

问题

ggplot2/knitr 强制绘图(在 LaTeX 中)具有默认纵横比。具有不同面数的两个图会导致面高不同的图。这不好。

我正在寻找一种解决方案,它可以独立于行分面的数量来控制 ggplot2 分面高度。

9 月 9 日编辑: 解决方案应该在一个块中工作,因为两个图都在一个块中(如示例代码中所示)。所以调整 knitr 的图形相关块选项是不可行的,因为块选项同样适用于两个图。

解决方案 - 但有问题

将每个图放入gridExtra 框并根据刻面数量缩放其高度,从而生成不再不同的刻面高度:更好但不完美。

  • 绘图显示在页面上的页边距过大,即使下面还有剩余的文字,所以绘图应该更靠近。
  • 似乎被此操作的地块被裁剪了。

是否有更智能且无问题的解决方案,可以独立于行分面数控制 ggplot2 分面高度?

\documentclass[a4paper]{article}
\usepackage[margin=1in]{geometry}

\begin{document}

<<setup, results='asis', message=FALSE, echo=FALSE>>=
require(ggplot2)
require(gridExtra)

### Generate two data frames

# Data frame with 2 classes
db.small = data.frame (
  class = as.factor(c(rep("A", 12), rep("B", 12))),
  month = as.factor(rep(1:12, 2)),
  value = runif(2*12, 0, 100)
  )

# Data frame with 5 classes
db.large = data.frame (
  class = as.factor(c(rep("A", 12), rep("B", 12), rep("C", 12), rep("C", 12), rep("D", 12))),
  month = as.factor(rep(1:12, 5)),
  value = runif(5*12, 0, 100)
)

# Generate plots
plot1 = ggplot(db.small, aes(month, value)) + geom_bar(stat="identity") + facet_grid(class ~ .) + ylim(c(0, 100))
plot2 = ggplot(db.large, aes(month, value)) + geom_bar(stat="identity") + facet_grid(class ~ .) + ylim(c(0, 100))
@

\section{Before: Native plots without modification}
Ggplot2/knitr forces both plots to have the default aspect ratio. As both plots have different number of facets the result is that the facet heights are different. This is not nice.

<<before, results='asis', message=FALSE, echo=FALSE, out.width="0.6\\linewidth">>=
print(plot1)
print(plot2)
@

\pagebreak
\section{After: Plots with modification}
Putting each plot into a gridExtra box and scaling it's height with the number of facets, results in facet heights which are no longer different: nicer but not perfect, see problems below.

<<After, results='asis', message=FALSE, echo=FALSE, out.width="0.6\\linewidth">>=
# Calculate number of facets for the two plots
db.small.numberfacets = length(unique(db.small$class))
db.large.numberfacets = length(unique(db.large$class))

# Define heights for modification of plots
facet.height = 4
other.height = 2

plot1 = plot1 + theme( plot.margin = unit(c(0, 0, 0, 0), "cm"))
plot2 = plot2 + theme( plot.margin = unit(c(0, 0, 0, 0), "cm"))

# Put plots inside a gridExtra box and change height plots
grid.arrange(arrangeGrob(plot1, heights=unit(db.small.numberfacets*facet.height+other.height, "cm")), nrow=1)
grid.arrange(arrangeGrob(plot2, heights=unit(db.large.numberfacets*facet.height+other.height, "cm")), nrow=1)
@


2 Problems:
\begin{itemize}
\item Plots appear on the page with too much margin, even there's remaining text below so plots shall move more closer.
\item Seems the second plot is cropped, see the x-axis label.
\end{itemize}

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.

\end{document}

pdf 输出:

【问题讨论】:

    标签: r ggplot2 knitr


    【解决方案1】:

    你知道 knitr chunk options 可以接受任意 R 表达式吗? example 40 展示了如何动态计算 fig.widthfig.height

    对于您的情况,您可以根据因子变量中用于分面的级别数为fig.height 分配一个值。例如,

    \documentclass{article}
    
    \begin{document}
    <<setup>>=
    library(ggplot2)
    calc_height = function(f) length(levels(f))
    p = ggplot(diamonds, aes(color)) + geom_bar()
    @
    
    <<test-a, fig.width=7, fig.height=calc_height(diamonds$cut)>>==
    p + facet_grid(cut ~ .)
    @
    
    <<test-b, fig.width=7, fig.height=calc_height(diamonds$clarity)>>==
    p + facet_grid(clarity ~ .)
    @
    
    \end{document}
    

    输出:

    【讨论】:

    • 是的,我知道这个块选项。因为我在一个块中有两个图(它是循环的一部分),所以块选项似乎不适用。我需要一个解决方案来控制每个图的刻面高度,即使它们属于同一个块。
    • 我已经更新了问题以澄清,该解决方案也应该适用于作为同一个 knitr 块的一部分的两个情节。谢谢。
    • @user2030503 我明白了。我只是还没有完全决定如何对fig.widthfig.height进行矢量化:现在它们根据dev进行矢量化,但我也可以更改设计,让它们根据绘图进行矢量化。
    • 这是个好消息。您能否发布代码 sn-p 将 fig.height 设置为矢量化块选项的外观?
    • @user2030503 例如dev=c('pdf', 'png'), fig.height=c(7, 5),那么pdf设备使用7,png在同一个图上使用5;在您的情况下,您需要将 fig.height 向量映射到同一块中的绘图而不是设备,这不是 fig.height 当前实现的方式
    猜你喜欢
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 2015-08-14
    • 2012-08-27
    • 1970-01-01
    • 2017-04-07
    • 2014-04-14
    • 2016-02-04
    相关资源
    最近更新 更多