Related
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()
I created a plot with two lines without any problem. The creation of the legend also worked without any problems. I just need to modify one line of the legend as it is dotted in the plot:
legend("bottom", legend = c("y", "y2", "A"), col = c("red", "orange", "blue"),
lwd=1, cex = 0.3)
so the line for A is dotted, how can I code this into R?
You can specify lty= , in the legend function, just that it's better to specify it before plotting, for example:
set.seed(111)
df = data.frame(x = 1:10, y =runif(10),y2=runif(10)+1,A=runif(10)-1)
col = c("red", "orange", "blue")
names(col) = c("y","y2","A")
linetypes = c(1,4,8)
names(linetypes) = c("y","y2","A")
plot(NULL,xlim=c(1,10),ylim=c(-2,2))
for(i in c("y","y2","A")){
lines(df$x,df[,i],col=col[i],lty=linetypes[i])
}
legend("bottom", legend = c("y", "y2", "A"),
col = c("red", "orange", "blue"), lty = linetypes,
lwd=1)
I have a plot that I made using qqmath in the Lattice package (I subset it to only 3 points to make it easier for an example).
table <- data.table(Col1=c(12,3,4), Col2 = c(54,4,6), Col3 = c("Pink", "Pink", "Red"))
PrbGrd <- qnorm(c(0.00001,0.0001,0.001,0.01, 0.05, 0.10,0.20,0.30,0.40,
0.50, 0.60, 0.70,0.80,0.90,0.95,0.99,0.999,0.9999,0.99999))
PrbGrdL<-c("0.001","0.01","0.1","1","5","10","20","30","40","50","60","70","80","90","95","99","99.9","99.99","99.999")
PrbGrdL2<- c("99.999","99.99","99.9","99","95","90","80","70","60","50","40","30","20","10","5","1","0.1","0.01","0.001")
ValGrd<- c(seq(0.001,0.01,0.001),seq(0.01,0.1,0.01),seq(0.1,1,0.1),seq(1,10,1),seq(10,100,10),seq(100,1000,100),seq(1000,10000,1000))
ValGrd<- log10(ValGrd)
ValGrd2 <- c(-2:20)
ProbPlot <- qqmath(~ Col1,
data= table,
distribution = function(p) qnorm(p),
main = "Normal probability plot",
pch=20,
cex=0.5,
xlab="Probability of Lower",
ylab = "Pb",
#xlim = c(max(PrbGrd),min(PrbGrd)),
xlim = c(min(PrbGrd),max(PrbGrd)),
scales=list(y=list(alternating=1),x = list(at = PrbGrd, labels = PrbGrdL, cex = 0.8)),
#yscale.components=yscale.components.log10ticks,
panel=function(x,...){
panel.abline(v=PrbGrd ,col="grey",lty=3)
panel.abline(h=ValGrd2,col="grey",lty=3)
panel.qqmath(x,distribution=qnorm)
}
)
I would like to use the colors that are in the 3rd column of my table (Col3) to change the colors of the respective point on the plot. I can't figure out how to do it within qqmath, this would be simple with the regular plot function... but it doesn't seem as simple with qqmath.
Thank you!
Updated: based on OP's comment.
You can add the col argument, like:
ProbPlot <- qqmath(~ Col1,
data = table,
distribution = function(p) qnorm(p),
main = "Normal probability plot",
pch = 20,
cex = 0.5,
xlab = "Probability of Lower",
ylab = "Pb",
#xlim = c(max(PrbGrd),min(PrbGrd)),
xlim = c(min(PrbGrd),max(PrbGrd)),
scales = list(y = list(alternating = 1),
x = list(at = PrbGrd,
labels = PrbGrdL,
cex = 0.8)),
#yscale.components=yscale.components.log10ticks,
panel = function(x, ...){
panel.abline(v = PrbGrd,
col = "grey",
lty = 3)
panel.abline(h = ValGrd2,
col = "grey",
lty = 3)
panel.qqmath(x,
distribution=qnorm,
col = table$Col3) # add colors for each point
}
)
I am doing the same scatter plots in 2D and 3D with ggplot2 and plot3d. I always like to do coord_fixed() in ggplot2 scatter plots when possible, for better readability. Is there a way to do the same in the scatter3D plot?
MWE:
data(iris)
head(iris)
library(ggplot2)
ggplot(iris, aes(x=Petal.Length, y=Petal.Width)) +
geom_point(pch=16) + theme_light() + coord_fixed()
library(plot3D)
scatter3D(iris$Petal.Length, iris$Sepal.Length, iris$Petal.Width, bty = "u", pch = 16, alpha = 0.5,
xlab = "Petal.Length", ylab = "Sepal.Length", zlab = "Petal.Width", phi = 0, theta = 40,
col.panel = "white", col.grid = "gray", col="black", ticktype = "detailed")
scale = FALSE does this:
scatter3D(iris$Petal.Length, iris$Sepal.Length, iris$Petal.Width, bty = "u", pch = 16, alpha = 0.5,
xlab = "Petal.Length", ylab = "Sepal.Length", zlab = "Petal.Width", phi = 0, theta = 40,
col.panel = "white", col.grid = "gray", col="black", ticktype = "detailed",
scale = FALSE)
From ?persp:
If scale is TRUE the x, y and z coordinates are transformed separately. If scale is FALSE the coordinates are scaled so that aspect ratios are retained
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.