Control the height of the chamfer ggplot2 regardless of the number of phase faces

Problem

ggplot2 / knitr forces graphics (in LaTeX) to have a default aspect ratio. Two sections, which have a different number of faces, lead to the fact that the graphs with the heights of the faces differ. It is unpleasant.

Example for problem

I was looking for a solution that controls ggplot2 chamfer height regardless of the number of line facets.

Edited September 9: The solution should work within the same fragment, since both graphs are in the same fragment (as in the code example). Thus, adjusting the parameters of the cube associated with the figure is not viable, since the piece option is applied to both graphs equally.

Solution - but with problems

By placing each graph in a gridExtra square and scaling its height with the number of faces, the results in the heights of the face that no longer differ are more pleasant, but not perfect.

  • Subjects appear on the page with too much margin, even where the text remains below, so the plots will move closer.
  • It seems that the plots handled by this are cropped.

Is there a smarter and more reliable solution that controls the height of the ggplot2 face regardless of the number of line facets?

\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 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 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 Output: Page 1Page 2

+7
r knitr ggplot2
source share
1 answer

Did you know that knitr chunk options can accept arbitrary R expressions? Example 40 shows how you can dynamically calculate fig.width and fig.height .

In your case, you can assign fig.height according to the number of levels in the factor variable for the cut. For example,

 \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} 

Output:

+3
source share

All Articles