Reputation: 524
Although I use a horizontal barplot as an example here, that itself is not the issue. The general issue is how to deal with the white space that is created around ggplots in rmarkdown after using
+coord_fixed(ratio=...)
To reduce the space used by barplots, especially with few factor, I prefer horizontal barplots, where I use coord_fixed(ratio=...) to have a sensible ratio between width and length of the bars.
The plot itself looks the way I want to (see first example below), but it has a lot of white space around it, which I tried to remove by using fig.height = ... in the knitr-header. As the next example shows, this didn't turn out well.
library(ggplot2)
library(ggstance)
library(dplyr)
X <- data.frame(X = sample(c("A", "B"), 30, replace = TRUE))
X <- X %>% group_by(X) %>% summarise(n = n())
ggplot(X, aes(y = X, x = n))+
geom_barh(stat = "identity")+
coord_fixed(ratio = 1)+
ggtitle("blub")
Using this inside rmarkdown where I used x = 3 ; x = 1 ; x=0.5:
```{r,fig.height = x}
# see code above
```
This results in:
fig.height=3
fig.height=1
fig.height=0.5
What I hoped it would do:
The latter clearly doesn't happen as the plot area gets narrower and the titles are moved to the inside of the plot.
I don't know if the solution is to be found inside ggplot or inside knitr. On top of that, an ideal solution should be easily automated for use inside a loop (adapt the solution to changing number of factors).
Upvotes: 5
Views: 4199
Reputation: 13680
You can pass parameters to the fig.width
and fig.height
chunk options. You just have to calculate them before evaluating that chunk:
---
output: html_document
---
```{r, message=FALSE}
library(ggplot2)
library(ggstance)
library(dplyr)
X <- data.frame(X = sample(c("A", "B"), 30, replace = TRUE))
X <- X %>% group_by(X) %>% summarise(n = n())
hei <- length(X$X) + 1
len <- max(X$n) + 2
```
Text before the plot
```{r, fig.height=hei, fig.width=len, echo=FALSE}
ggplot(X, aes(y = X, x = n))+
geom_barh(stat = "identity")+
coord_fixed(ratio = 1)+
ggtitle("blub") +
theme(plot.background = element_rect(fill = 'red'))
```
Text after the plot
```{r, message=FALSE}
X <- data.frame(X = sample(c("A", "B", "C"), 30, replace = TRUE))
X <- X %>% group_by(X) %>% summarise(n = n())
hei <- length(X$X) + 1
len <- max(X$n) + 2
```
Another plot
```{r, fig.height=hei, fig.width=len, echo=FALSE}
ggplot(X, aes(y = X, x = n))+
geom_barh(stat = "identity")+
coord_fixed(ratio = 1)+
ggtitle("blub") +
theme(plot.background = element_rect(fill = 'red'))
```
Upvotes: 3
Reputation: 6671
I think, you need to find the good ratio between height and width. But this is sometimes not easy to do.
Some time ago, I wrote a function to remove white margins of a PNG image. If you do not find the good ratio, you can try to use this one. This requires to save your figure as png with function ggsave
and then call it in a following chunk with knitr::include_graphics()
.
The function is the following one:
#' A function to crop white margins of a PNG image
#'
#' @param x path to the PNG image
#' @param pixel number of white pixels lines to keep
#' @export
Rm_WhiteMargins <- function(x, pixel = 2)
{
# Cut the output image to remove dirty white margins from corrplot
img <- png::readPNG(x)
img.test.row <- apply(img, 3, function(layer) {
apply(layer, 1, function(i) {(sum(i != 1) > 0)})
}) %>%
apply(., 1, function(i) {(sum(i) > 0)})
rowMin <- max(min(which(img.test.row[1:round(length(img.test.row) / 2)])) - (1 + pixel), 1)
rowMax <- min(max(c(1:length(img.test.row))[
round(length(img.test.row) / 2) : length(img.test.row)][
which(img.test.row[(length(img.test.row) / 2) : length(img.test.row)])]) + 1 + pixel,
length(img.test.row))
img.test.col <- apply(img, 3, function(layer) {
apply(layer, 2, function(i) {(sum(i != 1) > 0)})
}) %>%
apply(., 1, function(i) {(sum(i) > 0)})
colMin <- max(min(which(img.test.col[1:round(length(img.test.col) / 2)])) - (1 + pixel), 1)
colMax <- min(max(c(1:length(img.test.col))[
round(length(img.test.col) / 2) : length(img.test.col)][
which(img.test.col[(length(img.test.col) / 2) : length(img.test.col)])]) + 1 + pixel,
length(img.test.col))
# Remove rows and cols with white pixels from the original image
img <- img[rowMin:rowMax, colMin:colMax,]
png::writePNG(img, target = paste0(gsub(".png", "", x), "_crop.png"))
rm(img)
}
If this can help...
Upvotes: 0