Save par(mfrow) multipanel output as svg - r

I'm using par(mfrow) to generate a multi-panel plot of three separate graph output objects. Sample code below represents a very simplified version of the objects I have.
How can I save these plots as a single object with ggsave? I've tried naming the par(mfrow) as an object and plotting it, but that doesn't seem to work.
Any advice on alternative ways of generating/saving a multi-panel plot is also welcome! Please let me know if I can clarify the question or example. Thanks!
par(mfrow = c(1,3), mar = c(10, 5, 5, 3), xpd = TRUE)
hist(x = rnorm(100), col = "skyblue", main = "X")
hist(x = rnorm(50), col = "green", main = "Y")
legend("bottom", c("Blue", "Green", "Purple"),
title = "Sample Data", horiz = TRUE, inset = c(0, -0.4),
col = c("skyblue", "green", "purple"), pch = rep(15,2),
bty = "n", pt.cex = 1.5, text.col = "black")
hist(x = rnorm(75), col = "purple", main = "Z")

I would suggest using svglite over svg if you want to edit the graph using Inkscape or a similar program since you will not be able to edit the text (change the text, font, or size) in a file produced by svg. Here is an example with a few edits to your original code:
library(svglite)
svglite("MyPlots.svg", width=8, height=6)
par(mfrow = c(1,3), mar = c(10, 5, 5, 3), xpd = TRUE, mgp=c(1.75, .75, 0))
hist(x = rnorm(100), col = "skyblue", main = "X")
hist(x = rnorm(50), col = "green", main = "Y")
legend("bottom", c("Blue", "Green", "Purple"),
title = "Sample Data", horiz = TRUE, inset = c(0, -0.2),
col = c("skyblue", "green", "purple"), pch = rep(15,2),
bty = "n", pt.cex = 1.5, text.col = "black")
hist(x = rnorm(75), col = "purple", main = "Z")
dev.off()

Related

Factor variable on x-axis for double y-axis

Right now on the x-axis it plots numerical variable "1,2,3,4" etc. when instead I want it to graph the game. As you can see in line 85, axis(1,Champ$game) I want the game name on the x-axis, but instead it just numbers the game rather than putting the game name. How do I fix this?
par(mar=c(5, 4, 4, 6) + 0.1)
plot(Champ$daily_max_vel, pch = 16, axes = FALSE, ylim =
c(3.0,3.9),type = "b", col = "black", ylab = "", xlab = "",
main = "Athlete")
##Creates y-axis for graph 1
axis(2, ylim = c(0,1), col = "black", las = 1)
mtext("Velocity (m/s)", side = 2, line = 2.5)
box()
## Allows for second plot on same graph
par(new = TRUE)
#Plotting second graph
plot(Champ$daily_peak_power, pch = 1, xlab = "", ylab = "",
ylim = c(1000,1600), axes = FALSE, type = "b",
col = "orange")
#Creating Second Axis
mtext("Power (W)", side = 4, col = "orange", line = 4)
axis(4,ylim = c(1200,1600), col = "orange", col.axis =
"orange", las = 1)
axis(1,Champ$game)
Using the labels function should do what you are looking for - here is an example of what I think your issue is. If this doesn't work, edit your post to provide your data structure.
# create sample data
df <- data.frame(game = sample(c(1, 2, 3), 150, replace = TRUE),val = rgamma(150, 50))
plot(df)
# label factors
df$game <- factor(df$game, levels = 1:3, labels = c("Game A", "Game B", "Game C"))
# plot
plot(df, axes = F, type = "b")
axis(1, df$game, labels = df$game) # shows game A, game b, game c instead of 1, 2, 3

How to set limits of grid in barplot?

I am trying to put grids in my barplots, but they appear in front of the data and not in the background. I tried to fix this using
panel.first = grid()
As for the data I am trying to plot, the first column consists of the year numbers (2014-2021) and the second columns are the corresponding values (all vector classes are numeric). When trying to plot using the following code:
par(mfrow=c(1,2))
barplot(mean_trend[,2],names.arg = mean_trend[,1],col="skyblue",ylim = c(0.1,95),cex=0.8,cex.names=0.85,las=2,cex.lab=0.85,lwd=1.5,panel.first = grid())
mtext(side=2,line=2.3, "Average amount in mm", font=2, cex=0.8)
box(lwd=1.5)
barplot(freq_trend[,2],names.arg = freq_trend[,1],col="skyblue",ylim = c(2,4500),cex=0.85,cex.names=0.85,las=2,cex.lab=0.85,lwd=1.5,panel.first = grid())
box(lwd=1.5)
mtext(side=2,line=3.3, "Average flood frequency", font=2, cex=0.8)
I obtain the following result
As you can see, the grid is now behind the plotted data, but exceeds the box/plot limits. How can I fix this?
Kind regards
As you didn't add a data mean_trend - I give an example with other data.
About add and others arguments - you can read ?barplot
# One row, two columns
par(mfrow = c(1, 2))
#PLOT1
barplot(table(mtcars$cyl), main = "PLOT 1", col = c("yellow", "green", "red"), ylim = c(0, 15))
grid(nx = NULL, ny = NULL, lwd = 1, lty = 1, col = "gray")
barplot(table(mtcars$cyl), col = c("yellow", "green", "red"), ylim = c(0, 15), add = TRUE)
#PLOT2
barplot(table(mtcars$cyl), main = "PLOT 2", col = c("yellow", "green", "red"), ylim = c(0, 15))
grid(nx = NULL, ny = NULL, lwd = 1, lty = 1, col = "gray")
barplot(table(mtcars$cyl), col = c("yellow", "green", "red"), ylim = c(0, 15), add = TRUE)

Making a dark theme plot in R

Let say I want to draw this function f(x) = x^2. I want the graph of the function to be any color I want and everything else (except the axis) black. Is this possbile?
graphics.off()
par(bg = "black")
curve(x^2, -2, 2, col = "green", axes = FALSE, ann = FALSE)
title("my plot", xlab = "X", ylab = "X^2", col.lab = "white", col.main = "white")
box(col = "white")
axis(1, seq(-2, 2, 1), seq(-2, 2, 1), col = "white", col.axis = "white")
axis(2, seq(0, 4, 1), seq(0, 4, 1), col = "white", col.axis = "white")
Maybe you can ?plot to see how to make it. Below is just an example
plot(x<-seq(-5,5,0.1),
x**2,
main="square function",
ylab="f(x)=x^2",
type="l",
col=28)

R - Plot with two y axis, bars and points not aligned

For a customer I'm trying to do a combined barplot and lineplot (with points) with two y axis.
Problem: My bars and points are not aligned.
Background: We have several machines and are measuring their number of on/of switches and the amount of time that each machine is running. We want both information together in one plot to save space, because we have several machines.
The data is aggregated by day or hour. Here's some sample data:
date <- seq(as.Date("2016-10-01"), as.Date("2016-10-10"), "day")
counts <- c(390, 377, 444, NA, NA, NA, NA, 162, 166, 145)
runtime <- c(56.8, 59.4, 51.0, NA, NA, NA, NA, 38.5, 40.9, 43.4)
df <- data.frame(date = date, counts = counts, runtime = runtime)
Here's what I tried so far:
par(mar = c(3,4,4,4) + 0.3)
barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2)
par(new = TRUE)
ymax <- max(df$counts, na.rm = TRUE) * 1.05
plot(df$date, df$counts, type = "n", xlab = "", ylab = "", yaxt = "n",
main = "Machine 1", ylim = c(0, ymax))
abline(v = date, col = "red", lwd = 2.5)
lines(df$date, df$counts, col = "blue", lwd = 2)
points(df$date, df$counts, pch = 19, cex = 1.5)
axis(4)
mtext("Number of switching operations", side = 4, line = 3, font = 2)
I found some inspiration for two axis here: http://robjhyndman.com/hyndsight/r-graph-with-two-y-axes/
What can I do to get bars with their middle aligned with the points of the lineplot?
The problem you are running into is the call to the second plot function after the barplot. This is shifting/resizing the plotting canvas which is causing the shift in the subsequent points.
Here is a quick work-around that just rescales the points and lines onto the barplot. It saves the barplot as an object, which stores x-axis locations for the mid-points of the bars. Then, when you plot the abline, lines and points using 'bp' as the x-axis variable, they will be correctly aligned.
ymax <- max(df$counts, na.rm = TRUE) * 1.05
par(mar=c(4.1,5.1,2.1,5.1))
bp <- barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2, xlim=c(0.2,12), )
barplot(df$runtime, col = "palegreen2", ylab = "runtime in [%]", border="NA",
ylim = c(0,100), font.lab = 2)
abline(v = bp, col = "red", lwd = 2.5)
lines(bp, df$counts/ymax*100, col = "blue", lwd = 2)
points(bp, df$counts/ymax*100, pch = 19, cex = 1.5)
axis(4,at=c(0,20,40,60,80,100), labels=c("0","100","200","300","400","500"))
mtext("Number of switching operations", side = 4, line = 3, font = 2)
axis(1, at=bp, labels=df$date)
#emilliman: Thank you for your patience and input! Your plot is not completely correct, because the scaling of the second y-axis does not fit the points' values, but your idea helped me to find a solution!
Here's my new code:
library(plyr)
ymax <- max(df$counts, na.rm = TRUE)
ymax_up <- round_any(ymax, 100, f = ceiling)
ylab <- ymax_up/5 * c(0:5)
par(mar = c(3,4,4,4) + 0.3)
bp <- barplot(df$runtime, col = "palegreen2", border = "NA", ylab = "runtime in [%]",
ylim = c(0,100), font.lab = 2, main = "Machine 1")
abline(v = bp, col = "red", lwd = 2.5)
lines(bp, 100/ymax_up * df$counts, col = "blue", lwd = 2)
points(bp, 100/ymax_up * df$counts, pch = 19, cex = 1.5)
axis(4,at=c(0,20,40,60,80,100), labels= as.character(ylab))
mtext("Number of switching operations", side = 4, line = 3, font = 2)
xlab <- as.character(df$date, format = "%b %d")
axis(1, at=bp, labels = xlab)
abline(h = c(0,100))
(http://i.imgur.com/9YtYGSD.png)
Maybe this is helpful for others who run into this problem.

How to force the labels to fit in VennDiagram?

I use VennDiagram to make a venn diagram with the following example code:
library(VennDiagram)
venn.diagram(list(shams_90d = 1:3, shams_90d_4h = 2:4, sham3__shams_90d = 3:5,
sham3_90d__shams = 5:7, sham3_90d__shams_4h = 6:9),
fill = c("red", "green", "blue", "yellow", "purple"),
alpha = c(0.5, 0.5,0.5, 0.5, 0.5), cex = 1,cat.fontface = 2,
lty =1, filename = "trial2.emf");
Which gives this figure:
The names on the left and right of the figure are cut off, and a little bit of the name at the bottom as well. I tried changing width, but that makes the venn diagram itself get wider, and the names still get cut off.
How can I make the VennDiagram so that it includes the full names, either by adding more whitespace on the left and right of the diagram, or by pushing the names more towards the venn diagram?
You can justify the label text with cat.just. The package reference manual gives info. on how to pass the parameters.
For your example i used trial and error for the justification values.
# Plot
v <- venn.diagram(list(shams_90d = 1:3, shams_90d_4h = 2:4, sham3__shams_90d = 3:5,
sham3_90d__shams = 5:7, sham3_90d__shams_4h = 6:9),
fill = c("red", "green", "blue", "yellow", "purple"),
alpha = c(0.5, 0.5,0.5, 0.5, 0.5), cex = 1,cat.fontface = 2,
lty =1, filename=NULL, cat.cex=0.8,
cat.just=list(c(0.6,1) , c(0,0) , c(0,0) , c(1,1) , c(1,0)))
grid.newpage()
grid.draw(v)
Another option (if a bit of a quick hack) would be to remove the cat.just argument and set a smaller grid::viewport. You may need to tweak the width of your graphics window / output device (ie pdf(..., width=...)):
# Plot
v <- venn.diagram(list(shams_90d = 1:3, shams_90d_4h = 2:4, sham3__shams_90d = 3:5,
sham3_90d__shams = 5:7, sham3_90d__shams_4h = 6:9),
fill = c("red", "green", "blue", "yellow", "purple"),
alpha = c(0.5, 0.5,0.5, 0.5, 0.5), cex = 1,cat.fontface = 2,
lty =1, filename=NULL, cat.cex=0.8)
grid.newpage()
pushViewport(viewport(width=unit(0.8, "npc"), height = unit(0.8, "npc")))
grid.draw(v)

Resources