Change plot dimensions in ggplot2 - r

I want to create a single pdf file and put several plots in it using package ggplot2. However I need to reduce the width of one specific plot, among all. Here is the code:
invisible(pdf("foo.pdf"))
foo <- data.frame(x=rnorm(100), y=rnorm(100), class=factor(sample(2,1000,T)))
ggplot(foo, aes(x=x,y=y))+geom_point() # first plot
# For next plot I want to reduce the width
ggplot(foo, aes(x=class,y=y)) + geom_boxplot()
invisible(dev.off())
How to do it?

You can print in a viewport smaller than the full page,
library(grid)
grid.rect(width=unit(0.8, "npc"), gp=gpar(lty=2))
print(qplot(1,1), vp=viewport(width=unit(0.8, "npc")))

Related

Arrange list of ggplot plots and adjust spacing/margin

I have a function that creates a list of ggplot plots. I'm currently using patchwork to arrange the plots together in a way that I can knit to Word, but I'm having a hard time with the way it looks when it renders. The output currently looks like this:
I'd like to make it so that it looks like this:
Currently, my code is the following:
patchwork_plots <- Reduce(`+`, plots)
patchwork_plots +
plot_layout(ncol=2)
I've tried a few different packages and different ways of adjusting, but nothing really seems to work. Any suggestions would be great.
A simple solution is to just change your aspect ratio and width= and height= of the plot. The graphics in your plots will not scale the same as the text in the plot, but will depend on the resolution and size/aspect ratio of your graphics device. Here is an example that shows 3 very different-looking plots that can result from adjusting the aspect ratio of your output.
library(ggplot2)
# intentionally crowded plot
gplot(mtcars, aes(mpg, disp)) + geom_point() +
facet_wrap(factor(cyl)~factor(carb), scales='free') +
labs(x='mpg is here and this is long', y='disp is here and this is long too!')
Width = 4, Height = 3
ggsave('plot4_3.png', width=4, height=3)
Width = 8, Height = 5
ggsave('plot8_5.png', width=8, height=5)
Width = 12, Height = 9
ggsave('plot12_9.png', width=12, height=9)

Smaller gap between two legends in one plot (e.g. color and size scale)

how do I reduce the gap between two guides in one plot. In the example below, the two guides are from a color and size scale and I want to change the gap between the two so that the title 'size' is right below the legend-point for 1. Design-wise, it might not make sense in this example but in my actual application it does.
df=data.frame(x=rnorm(100),y=rnorm(100),color=factor(rbinom(100,1,0.5)),size=runif(100))
ggplot(df,aes(x=x,y=y,color=color,size=size)) + geom_point()
Edit: Here is the plot. I would like to make the gap highlighted by the green line and the arrow smaller.
Now it seems to be possible using the theme parameters:
ggplot(df,aes(x=x,y=y,color=color,size=size)) + geom_point() +
theme(legend.spacing.y = unit(-0.5, "cm"))
You can also try to decrease margins of the legends:
legend.margin = margin(-0.5,0,0,0, unit="cm")
or older
legend.margin=unit(0, "cm")
I tried to play to customize legend or guide parameters but I can't find a solution. I hope give a solution using ggplot2 settings.
Here 2 solutions based on the gtable and grid packages.
for the gtable solution, the code is inspired from this question.
library(gtable)
# Data transformation
data <- ggplot_build(p)
gtable <- ggplot_gtable(data)
# Determining index of legends table
lbox <- which(sapply(gtable$grobs, paste) == "gtable[guide-box]")
# changing the space between the 2 legends: here -0.5 lines
guide <- gtable$grobs[[lbox]]
gtable$grobs[[lbox]]$heights <- unit.c(guide$heights[1:2],
unit(-.5,'lines'), ## you can the GAP here
guide$heights[4:5])
# Plotting
grid.draw(gtable)
Similar using the grid package ( we redraw in the viewport of the legend)
pp <- grid.get('guide',grep=T)
depth <- downViewport(pp$wrapvp$name)
guide <- grid.get('guide',grep=T)
grid.rect(gp=gpar(fill='white'))
guide$heights <- unit.c(guide$heights[1:2],unit(-0.2,'lines'),guide$heights[4],unit(0.1,'lines'))
grid.draw(guide)
upViewport(depth)

How to plot matrix with background color varying according to entry?

I wanted to ask for any general idea about plotting this kind of plot in R which can compare for example the overlaps of different methods listed on the horizontal and vertical side of the plot? Any sample code or something
Many thanks
A ggplot2-example:
# data generation
df <- matrix(runif(25), nrow = 5)
# bring data to long format
require(reshape2)
dfm <- melt(df)
# plot
require(ggplot2)
ggplot(dfm, aes(x = Var1, y = Var2)) +
geom_tile(aes(fill = value)) +
geom_text(aes(label = round(value, 2)))
The corrplot package and corrplot function in that package will create plots similar to what you show above, that may do what you want or give you a starting point.
If you want more control then you could plot the colors using the image function, then use the text function to add the numbers. You can either create the margins large enough to place the text in the margins, see the axis function for the common way to add text labels in the margin. Or you could leave enough space internally (maybe use rasterImage instead of image) and use text to do the labelling. Look at the xpd argument to par if you want to add the lines and the grconvertX and grconvertY functions to help with the coordinates of the line segents.

automatically adjust R plot size in a PDF output

When using the pdf() function in R for saving a plot in an external file, we can specify width and/or height to adjust the size of the plot. However, there are situations when we obtain multiple plot (say using par(mfrow=c(2,4))). In this situation, it's kind of difficult to determine what is the best width and height for the PDF file in order to have all plots displayed properly. Is there a way to let R automatically "fit the plots" in the PDF file? I searched the arguments in pdf() and tried some, but the results are not satisfactory. Thank you very much!
How about something using ggplot?
require(ggplot2)
# Bogus data
x <- rnorm(10000)
y <- as.factor(round(rnorm(10000, mean=10, sd=2), 0))
df <- data.frame(vals=x, factors=y)
myplot <- ggplot(data=df, aes(x=vals)) +
geom_density() +
facet_wrap(~ factors)
ggsave(filename="~/foo.pdf", plot=myplot, width=8, height=10, units="in")
EDIT: Should you need to print over multiple pages, see this question.

Increasing the plot area in ggplot to cope with geom_text at plot edges

How do I increase the grey plot area of a chart with one factor based axis and one numerical axis so that text labels in geom_text() plots are in view and do not extend outside the plot area?
In particular, I would like to extend the grey area to provide a margin area within the plot area that allows the text labels to appear in full.
Or is there a better way?
You can change the layout option of each ggplot using ggplot_gtable, then display all plots using grid.arrange.
library(ggplot2)
library(gridExtra)
## create a dummy ggplot
(g1 <- ggplot(mtcars, aes(wt, mpg)) +
geom_text(aes(label=rownames(mtcars)), size=6, angle=45) +
theme(plot.margin = unit(rep(1, 4), "cm")))
Obviously the text labels do not extend outside the plot area. But the following code allows just that:
gg_table <- ggplot_gtable(ggplot_build(g1))
gg_table$layout$clip[gg_table$layout$name=="panel"] <- "off"
grid.draw(gg_table)
Create a gg_table for each panel, then use grid.arrange to display all:
grid.arrange(gg_table, gg_table, gg_table, gg_table, ncol=2)
I know this is labor intensive, but you can write a function to create multiple ggplots and gg_tables to save time.

Resources