How to place categorical labels on right side of barchart? - r

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)

Related

How to edit ticks and tick labels in ggusrvplot, like in ggplot2?

I want to only have labels every second number, but have the small ticks for every number in my graph. As you can see in the figure I added, the labels are every 2nd tick on the X-axis.
But I want to achieve the result that's on the Y-axis:
With ggplot, this is possible with ggh4x and if_elfse. But I can't find a way how to do this in ggsurvplot. This is my code, for the first picture. The code for the second picture is found here: Code 2
ggsurvplot(fit, data = d,
conf.int = F,
censor = F,
palette = c("green", "purple", "red"),
legend.labs = c("Reference water (pH 7.3)\n(N = 66)",
"Acidic al-poor (pH 5.8)\n(N = 66)",
"Acidic al-rich (pH 5.8)\n(N = 66)"),
legend.title = "Water quality",
xlab = "Days",
xlim = c(1,23),
break.time.by = 2
)
Thank you in advance for yor help.
As ggsurvplot returns a list containing the plot as a ggplot2 object you could achieve your desired result using ggh2x by overriding the x scale as in the example code by #tjebo from Adding minor tick marks to the x axis in ggplot2 (with no labels).
Making use of the default example from ?ggsruvplot:
library(survminer)
library(survival)
library(ggh4x)
fit<- survfit(Surv(time, status) ~ sex, data = lung)
p <- ggsurvplot(fit, data = lung, main = "Survival curve",
xlab = "Days",
xlim = c(1,23))
p$plot +
scale_x_continuous(minor_breaks = seq(0, 24, 1), breaks = seq(0, 24, 2), guide = "axis_minor") +
theme(ggh4x.axis.ticks.length.minor = rel(1))
#> Scale for 'x' is already present. Adding another scale for 'x', which will
#> replace the existing scale.

ggplot using second data source for error bars fails

This is a follow-on to a previous question about getting some custom error bars.
The look of the plot is how I need it, so don't worry about commenting in solely in regards to that (happy to hear opinions attached to other help though)
Because these plots are generated in a loop, and the error bars are actually only added if a condition is met, I cant simply merge all the data up front, so assume for the purpose of this exercise the plot data and errorbar data are from different dfs.
I have a ggplot, to which I attempt to add some error bars using a different dataframe. When I call the plot, it says that it cannot find the y values from the parent plot, even though I'm just trying to add error bars using new data. I know this has to be a syntax error but I am stumped...
First lets generate data and the plot
library(ggplot2)
library(scales)
# some data
data.2015 = data.frame(score = c(-50,20,15,-40,-10,60),
area = c("first","second","third","first","second","third"),
group = c("Findings","Findings","Findings","Benchmark","Benchmark","Benchmark"))
data.2014 = data.frame(score = c(-30,40,-15),
area = c("first","second","third"),
group = c("Findings","Findings","Findings"))
# breaks and limits
breaks.major = c(-60,-40,-22.5,-10, 0,10, 22.5, 40, 60)
breaks.minor = c(-50,-30,-15,-5,0, 5, 15,30,50)
limits =c(-70,70)
# plot 2015 data
ggplot(data.2015, aes(x = area, y = score, fill = group)) +
geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
coord_flip() +
scale_y_continuous(limit = limits, oob = squish, minor_breaks = breaks.minor,
breaks = breaks.major)
Calling the plot (c) produces a nice plot as expected, now lets set up the error bars and attempt to add them as a new layer in the plot "c"
# get the error bar values
alldat = merge(data.2015, data.2014, all = TRUE, by = c("area", "group"),
suffixes = c(".2015", ".2014"))
alldat$plotscore = with(alldat, ifelse(is.na(score.2014), NA, score.2015))
alldat$direction = with(alldat, ifelse(score.2015 < score.2014, "dec", "inc"))
alldat$direction[is.na(alldat$score.2014)] = "absent"
#add error bars to original plot
c <- c+
geom_errorbar(data=alldat, aes(ymin = plotscore, ymax = score.2014, color = direction),
position = position_dodge(width = .9), lwd = 1.5, show.legend = FALSE)
When I call c now, I get
"Error in eval(expr, envir, enclos) : object 'score' not found"
Why does it look for data.2015$score when I just want it to overlay the geom_errorbar using the second alldat dataframe?
EDIT* I've tried to specify the ymin/ymax values for the error bars using alldata$plotscore and alldat$score.2014 (which I am sure is bad practice), it plots, but the bars are in the wrong positions/out of order with the plot (e.g. swapped around, on the benchmark bars instead, etc.)
In my experience, this error about some variable not being found tells me that R went to look in a data.frame for a variable and it wasn't there. Sometimes the solution is as simple as fixing a typo, but in your case the score variable isn't in the dataset you used to make your error bars.
names(alldat)
[1] "area" "group" "score.2015" "score.2014" "plotscore" "direction"
The y variable is a required aesthetic for geom_errorbar. Because you set a y variable globally within ggplot, the other geoms inherit the global y unless you specifically map it to a different variable. In the current dataset, you'll need map y to the 2015 score variable.
geom_errorbar(data=alldat, aes(y = score.2015, ymin = plotscore,
ymax = score.2014, color = direction),
position = position_dodge(width = .9), lwd = 1.5, show.legend = FALSE)
In your comment you indicated you also had to add fill to geom_errobar, as well, but I didn't find that necessary when I ran the code (you can see above that group is a variable in the second dataset in the example you give).
The other option would be to make sure the 2015 score variable is still named score after merging. This can be done by changing the suffixes argument in in merge. Then score will be in the second dataset and you won't have to set your y variable in geom_errorbar.
alldat2 = merge(data.2015, data.2014, all = TRUE, by = c("area", "group"),
suffixes = c("", ".2014"))
...
names(alldat2)
[1] "area" "group" "score" "score.2014" "plotscore" "direction"

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)))

lattice grid.arrange expand graphs within grid

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.

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):

Resources