I want to add space between plots but when I play with margin, it either overlaps or cuts.
Here is the code:
library(plotly)
plotList <- function(nplots) {
lapply(seq_len(nplots), function(x) plot_ly())
}
s1 <- subplot(plotList(6), nrows = 2, shareX = TRUE, shareY = TRUE)
s2 <- subplot(plotList(2), shareY = TRUE)
p <- subplot(s1, s2, plot_ly(), nrows = 3, margin = 0.04, heights = c(0.6, 0.3, 0.1))
print(p)
I obtain this:
Whereas i would rather like something like this (image done with paint) with more spacing between the different subplots:
How should I do ?
I was facing the same problem but, fortunately, I found a solution. You can use margin as an argument in Subplot function as follows:
subplot(plot1,
plot2,
nrows = 2,
margin = 0.07)
According to Plotly documentation, you can define only one or four values for each of the margins and those values should be between 0 and 1. If you provide only one value it will be used for all four margins or if you provide four values it will be used in the following order: the first one will be the left margin, the second one will be the right margin, the third one will be the top margin and the last one will be the bottom margin. You can play around and define the values that better fit the layout you want to create.
I found a solution by inserting blank plots between the normal plot. It is however a bit awkward but it works and I've found nothing better
blankplot<-plot_ly()%>%
layout(xaxis=list(visible="FALSE",color="white",tickfont =list(color="white")),
yaxis=list(visible="FALSE",color="white",tickfont =list(color="white")))
Related
I have a list of plots that I have assigned names to, and then converted to plot titles as suggested by https://stackoverflow.com/a/14790376/9335733. The titles happen to appear over the top x-axis title and so I attempt to move them as suggested here: https://stackoverflow.com/a/44618277/9335733. The overall code looks as follows:
lapply(names(Cast.files), function (x) plot(Cast.files[[x]],
main = x,
adj = 0, #adjust title to the farthest left
line =2.5 #adjust title up 2.5
)
)
It should be noted that plot is now converted from base R to the oce package for analyzing oceanographic data, but calls the same arguments from base R plot.
The problem becomes that in trying to move the title, the axis labels move as well and overlap. Any suggestions?
Edit: Here is what the image looks like before:
And after:
You might also want to look into the oma= argument in par(), which provides an "outer" margin which can be used to put a nice title. Something like:
library(oce)
data(ctd)
par(oma=c(0, 0, 1, 0))
plot(ctd)
title('Title', outer=TRUE)
This was solved by adding a title argument outside of the plot function as follows:
lapply(names(Cast.files), function (x) plot(Cast.files[[x]],
which = c("temperature", "salinity", "sigmaT","conductivity"),
Tlim = c(11,12),
Slim = c(29,32),
col = "red")
+ title(main = x, adj = 0.48, line = 3.5)#adding the titles at a specific location
)
This allowed for plots that looked like:
If you use the title function, rather than setting main within plot, it would allow you to change the line without affecting anything else in the plot.
Let's say I generate 5 sets of random data and want to visualize them using boxplots and save those to a file "boxplots.png". Using the code
png("boxplots.png")
data <- matrix(rnorm(25),5,5)
boxplot(data, names = c("Name1","Name2","Name3","Name4","Name5"))
dev.off()
there are 5 boxplots created as desired in "boxplots.png", however the names for the second ("Name2") and the fourth ("Name4") boxplot are omitted. Even changing the window of my png-view makes no difference. How can I avoid this behavior?
Thank you!
Your offered code does not produce an overlap in my setting, but that point is relatively moot: you want a way to allow more space between words.
One (brute-force-ish) way to fix the symptom is to alternate putting them on separate lines:
set.seed(42)
data <- matrix(rnorm(25),5,5)
nms <- c("Name1","Name2","Name3","Name4","Name5")
oddnums <- which(seq_along(nms) %% 2 == 0)
evennums <- which(seq_along(nms) %% 2 == 1)
(There's got to be a better way to do that, but it works.)
From here:
png("boxplot.png", height = 240)
boxplot(data, names = FALSE)
mtext(nms[oddnums], side = 1, line = 2, at = oddnums)
mtext(nms[evennums], side = 1, line = 1, at = evennums)
dev.off()
(The use of png is not important here, I just used it because of your edit.)
The gridExtra package adds a grob of class "pattern" that lets one fill rectangles with patterns. For example,
library(gridExtra)
grid.pattern(pattern = 1)
creates a box filled with diagonal lines. I want to create a stack of panels in which each panel is filled with these diagonal lines. This is easy:
library(lattice); library(gridExtra)
examplePlot <- xyplot(
1 ~ 1 | 1:2,
panel = function () grid.pattern(pattern = 1),
layout = c(1, 2),
# Remove distracting visual detail
scales = list(x=list(draw=FALSE), y=list(draw=FALSE)),
strip = FALSE, xlab = '', ylab = ''
)
print(examplePlot)
The problem is that the diagonal lines aren't aligned across panels. That is, there is a visual "break" where the bottom of the first panel meets the top of the second panel: at that point, the lines don't line up. This is the problem that I want to fix.
I can eliminate most of the visual break by adding the argument pattern.offset = c(.2005, 0) to the grid.pattern call, and making sure that it applies only to the bottom panel. But this solution doesn't generalize. For example, if I change the pattern (e.g., by using the granularity argument to grid.pattern), this solution won't work. Is there a more general fix?
To make this work, you'll have to take charge of setting the panel.height argument used by print.trellis. (To see why, try resizing your plotting device after running your example code: as the size of the device and the panels changes, so does the matching/mismatching of the lines):
## Calculate vertical distance (in mm) between 45 degree diagonal lines
## spaced 5mm apart (the default distance for grid.pattern).
vdist <- 5 * sqrt(2)
nLines <- 8L ## can be any integer
panelHeight <- list(x = nLines*vdist, units = "mm", data = NULL)
## Plot it
print(examplePlot, panel.height=panelHeight)
I have a multiple variable time series were some of the variables have rather large ranges. I wish to make a single-page plot with multiple stacked plots of each variable were some of the variables have a log10 y-axis scaling. I am relatively new to lattice and have not been able to figure out how to effectively mix the log10 scaling with non-transformed axes and get a publication quality plot. If print.trellis is used the plots are not aligned and the padding needs some work, if c.trellis is used the layout is good, but only the y-scaling from only one plot is used. Any suggestions for an efficient solution, where I can replicate the output of c.trellis using the different y-scaling for each (original) object?
Example below:
require(lattice)
require(latticeExtra)
# make data.frame
d.date <- as.POSIXct(c("2009-12-15", "2010-01-15", "2010-02-15", "2010-03-15", "2010-04-15"))
CO2dat <- c(100,200,1000,9000,2000)
pHdat <- c(10,9,7,6,7)
tmp <- data.frame(date=d.date ,CO2dat=CO2dat ,pHdat=pHdat)
# make plots
plot1 <- xyplot(pHdat ~ date, data=tmp
, ylim=c(5,11)
, ylab="pHdat"
, xlab="Date"
, origin = 0, border = 0
, scales=list(y=list(alternating=1))
, panel = function(...){
panel.xyarea(...)
panel.xyplot(...)
}
)
# make plot with log y scale
plot2 <- xyplot(CO2dat ~ date, data=tmp
, ylim=c(10,10^4)
, ylab="CO2dat"
, xlab="Date"
, origin = 0, border = 0
, scales=list(y=list(alternating=1,log=10))
, yscale.components = yscale.components.log10ticks
, panel = function(...){
panel.xyarea(...)
panel.xyplot(...)
# plot CO2air uatm
panel.abline(h=log10(390),col="blue",type="l",...)
}
)
# plot individual figures using split
print(plot2, split=c(1,1,1,2), more=TRUE)
print(plot1, split=c(1,2,1,2), more=F)
# combine plots (more convenient)
comb <- c(plot1, plot2, x.same=F, y.same=F, layout = c(1, 2))
# plot combined figure
update(comb, ylab = c("pHdat","log10 CO2dat"))
Using #joran's idea, I can get the axes to be closer but not exact; also, reducing padding gets them closer together but changes the aspect ratio. In the picture below I've reduced the padding perhaps by too much to show the not exactness; if this close were desired, you'd clearly want to remove the x-axis labels on the top as well.
I looked into the code that sets up the layout and the margin on the left side is calculated from the width of the labels, so #joran's idea is probably the only thing that will work based on the printing using split, unless one were to rewrite the plot.trellis command. Perhaps the c method could work but I haven't found a way yet to set the scale components separately depending on the panel. That does seem more promising though.
mtheme <- standard.theme("pdf")
mtheme$layout.heights$bottom.padding <- -10
plot1b <- update(plot1, scales=list(y=list(alternating=1, at=5:10, labels=paste(" ",c(5:10)))))
plot2b <- update(plot2, par.settings=mtheme)
pdf(file="temp.pdf")
print(plot2b, split=c(1,1,1,2), more=TRUE)
print(plot1b, split=c(1,2,1,2), more=F)
I would like two plots to show up in two seperate spaces in the plot so I do:
par(mfrow=c(1,2))
plot(1:10,1:10)
Now I would like the second plot to be about 25% shorter than the first plot so I adjust omd:
tmp <- par()$omd
tmp[4] <- 0.75
par(omd=tmp)
plot(1:10,1:10)
The problem is that the second plot shows up ontop of the first plot. How do I avoid this margin issue?
Maybe try using layout instead?
layout(matrix(c(1, 1, 0, 2), ncol = 2L), widths = c(1,1),heights = c(0.5,1))
par(mar = c(3,2,2,2))
plot(1:10,1:10)
par(mar = c(3,2,2,2))
plot(1:10,1:10)
I guess maybe you'd want to set the heights to c(0.2,0.8) to get a 25% reduction?
Edit
But I don't think that omd does what you think it does. It changes the region inside the outer margins, which will always include both plot regions when setting par(mfrow = c(1,2)). What you really want to change, I think is plt, which alters the size of the current plotting region (using quartz, as I'm on a mac):
quartz(width = 5,height = 5)
par(mfrow=c(1,2))
vec <- par("plt")
plot(1:10,1:10)
par(plt = vec * c(1,1,1,0.75))
plot(1:5,1:5)