lattice grid.arrange expand graphs within grid - r

I´m starting with lattice. I have several plots and I want to dispose then with grid.arrange
Here´s an example for two graphs
graph1<-useOuterStrips(barchart(value1~Var1|Var2+Var3,data=table.df, ylab=NULL)
graph2<-useOuterStrips(barchart(value2~Var1|Var2+Var3,data=table.df, ylab=NULL)
grid.arrange(graph1,graph2, nrow=2, ncol=2, left=("percentage"))
It works well, however I would like to change the heighs of each rown on the grid (to expand the graphs). I have tried to inlcude the argument heighs on grid.arrange but doesn´t seens to do the job.
Any suggestion?

The correct argument to pass to grid.arrange and be passed to grid.layout is heights.
That being said, if you send it identical heights for all cells in the layout, the heights will stay the same. You may need to increase the size of your plotting device.
If you want different heights for each row you can.
Using the example from ?barchart
x <-barchart(yield ~ variety | site, data = barley,
groups = year, layout = c(1,6), stack = TRUE,
auto.key = list(space = "right"),
ylab = "Barley Yield (bushels/acre)",
scales = list(x = list(rot = 45)))
y <-barchart(yield ~ variety | site, data = barley,
groups = year, layout = c(1,6), stack = TRUE,
auto.key = list(space = "right"),
ylab = "Barley Yield (bushels/acre)",
scales = list(x = list(rot = 45)))
grid.arrange(x,y,ncol=1, heights = c(1.5,2))
Which is ugly and useless, but shows the concept.

Related

How to make three different bar charts of similar type clustered in the same plot?

I need to map my Erosion values for different levels of tillage (colomns) with three levels of soil depth (rows (A1, A2, A3)). I want all of this to be shown as a barchart in a single plot.
Here is a reproducible example:
a<- matrix(c(1:36), byrow = T, ncol = 4)
rownames(a)<-(c("A1","B1","C1","A2","B2","C2","A3","B3","C3"))
colnames(a)<-(c("Int_till", "Redu_till", "mulch_till", "no_till"))
barplot(a[1,], xlab = "A1", ylab = "Erosion")
barplot(a[4,], xlab = "A2", ylab = "Erosion")
barplot(a[7,], xlab = "A3", ylab = "Erosion")
##I want these three barchart side by side in a single plot
## for comparison
### and need similar plots for all the "Bs" and "Cs"
### Lastly, i want these three plots in the same page.
I have seen people do similar things using "fill" in ggplot (for lines) and specifying the factor which nicely separates the chart for different categories but I tried doing it but always run into error maybe because my data is continuous.
If any body could help me with these two things.. It will be a great help. I will appreciate it.
Thank you!
We can use ggplot
library(reshape2)
library(ggplot2)
library(dplyr)
melt(a) %>%
ggplot(., aes(x = Var2, y = value, fill = Var1)) +
geom_bar(stat = 'identity',
position = position_dodge2(preserve = "single")) +
facet_wrap(~ Var1)
Set mfcol to specify a 3x3 grid and then for each row generate its bar plot. Also, you could consider adding the barplot argument ylim = c(0, max(a)) so that all graphs use the same Y axis. title and mtext can be used to set the overall title and various margin text as we do below. See ?par, ?title and ?mtext for more information.
opar <- par(mfcol = c(3, 3), oma = c(0, 3, 0, 0))
for(r in rownames(a)) barplot(a[r, ], xlab = r, ylab = "Erosion")
par(opar)
title("My Plots", outer = TRUE, line = -1)
mtext(LETTERS[1:3], side = 2, outer = TRUE, line = -1,
at = c(0.85, 0.5, 0.17), las = 2)

How to change the legend title and position in a lattice plot

I'm using lsmip from lsmeans to plot my model,
library(lsmeans)
PhWs1 <- lsmip(GausNugget1, Photoperiod:Ws ~ Month,
ylab = "Observed log(number of leaves)", xlab = "Month",
main = "Interaction between Photoperiod and Water stress over the months (3 photoperiods)",
par.settings = list(fontsize = list(text = 15, points = 10)))
but I was not able to get a suggestion on the internet on how to handle the legend position, size, title, etc.
I used trellis.par.get() to see the parameters but I could not find the one related to my issue. As you can see from the graph, the legend should be "Photoperiod*Ws" but Ws is not visible.
I see two possibly complementing alternatives to approach this issue. The first would be to create a fully customized legend and pass it on to the key argument of xyplot (which lsmip is heavily based on). Here is an example taken from ?lsmip to clarify my point.
## default trellis point theme
trellis_points <- trellis.par.get("superpose.symbol")
## create customized key
key <- list(title = "Some legend title", # legend title
cex.title = 1.2,
x = .7, y = .9, # legend position
points = list(col = trellis_points$col[1:2], # points
pch = trellis_points$pch[1:2],
cex = 1.5),
text = list(c("A", "B"), cex = .9)) # text
## create results and extract lattice plot
d <- lsmip(warp.lm, wool ~ tension, plotit = FALSE,
main = "Some figure title", key = key)
p <- attr(d, "lattice")
p
As you can see, setting up a customized legend let's you modify all the different components of the legend - including labels, text and symbol sizes, legend spacing, etc. Have a deeper look at the key argument described in ?xyplot which describes the various modification options in detail.
Now, if you have a long legend title and you do not want to include the legend inside the plot area, you could also define separate viewports, thus allowing the legend to occupy more space at the right margin. Note the use of update to remove the initially created legend from p and the subsequent assembly of the single figure components using grid functionality.
## remove legend from figure
p <- update(p, legend = NULL)
## assemble figure incl. legend
library(grid)
png("plot.png", width = 14, height = 10, units = "cm", res = 300)
grid.newpage()
## add figure without legend
vp0 <- viewport(x = 0, y = 0, width = .75, height = 1,
just = c("left", "bottom"))
pushViewport(vp0)
print(p, newpage = FALSE)
## add legend
upViewport(0)
vp1 <- viewport(x = .7, y = 0, width = .3, height = 1,
just = c("left", "bottom"))
pushViewport(vp1)
draw.key(key, draw = TRUE)
dev.off()

How to manually set the scale for multiple boxplots in lattice bwplot?

I've got the results of clustering and decided to make a boxplot for each cluster, using lattice.
Next, I was faced with the need to establish a scale, acceptable to all cluster boxplots.
Found a solution, which allows to exclude an outliers and set free relation.
library(lattice)
trellis.device(new=FALSE, col=FALSE)
bwplot(value ~ variable | Cluster, data = test,
layout = c(2,2),
prepanel = function(x, y) {
bp <- boxplot(split(y, x), plot = FALSE)
ylim <- range(bp$stats)
list(ylim = ylim) },
scales = list(y = list(relation = "free")),
do.out = F)
So, I've got pretty good plots, but it can be better, if I manually set the ylim for each plot. Eg there is only integer values in my data and the value 0.5 at upper left cluster graph is meaningless.
So, is there any way to set multiple ylims in bwplot parameters?
From the documentation under ?bwplot:
xlim could also be a list, with as many components as the number of panels (recycled if necessary), with each component as described above. This is meaningful only when scales$x$relation is "free", in which case these are treated as if they were the corresponding limit components returned by prepanel calculations.
The ylim argument has the corresponding functionality for the y-axis.
So, set relation = "free" in the scales argument as you did, and then pass a list to the ylim argument to individually set the y-axis limits for each panel:
bwplot(len ~ factor(dose) | supp, data = ToothGrowth,
scales = list(relation = "free"),
ylim = list(c(5, 31), c(0, 36)))

R-Lattice package: 1 x-axis for multiple y-axes

My question is similar to this:
Plotting bar plot below xyplot with same x-axis?, but for the lattice package rather than ggplot.
I have 21 xyplots, all with the same x-axis scale, but different y-axis scales. I would like to plot all 21 lines with only 1 x-axis, but 21 different y-axes scales (one row per line). I nearly have it here:, but the redundant x-axes printed to each panel make this figure ridiculous. My script:
xyplot(numhr~year | spp, xlab = "Time(years)",
ylab = "Abundance (# per party hr)", type = "l", aspect = "fill",
strip = FALSE, scales = list(relation = "free"), as.table = TRUE,
layout = c(1,21), xlim = c(1940,2010))
Any help?
~Kevin
As per the comment above, the necessary change to my code to make this work involves adding 'y = list(relation = "free")' to the 'scales' component. Edited code below:
xyplot(numhr~year | spp, xlab = "Time(years)",
ylab = "Abundance (# per party hr)", type = "l", aspect = "fill",
strip = FALSE, scales = list(y = list(relation = "free")), as.table = TRUE,
layout = c(1,21), xlim = c(1940,2010))
Which produces this (unfortunately the y-axes are still too condensed, but this does address the question originally posed):

How to place categorical labels on right side of barchart?

In the default Lattice barchart, categorical variable labels are placed on the left. I want to put them on the right as well. I can manipulate locations of numeric ticks and labels using scales, but have had no success in moving the categorical labels. Study of help(barchart) and Sarkar's book has not led to the answer (which is not to say the answer isn't there).
You were on the right track with the scales argument. Try adding alternating = 3 to the list of y scale parameters.
barchart(variety ~ yield, data = barley, groups = year, stack = TRUE,
ylab = "Barley Yield (bushels/acre)",
scales = list(x = list(rot = 45), y = list(alternating = 3)),
horizontal = TRUE)

Resources