ggplot2 , ggroc changing axis ticks - r

I've been trying to change my axes ticks with scale_x_discrete, continuous and nobody seems to work, i either get an error or they just dont change. Also im looking for a way to "move" both of my axes so my plot could look like the provided example.
library(ggplot2)
library(pROC)
library(dplyr)
#some data
data(aSAH)
# store roc object
roc.ob <- roc(outcome ~ s100b, aSAH, percent = T)
ggroc(roc.ob) +
coord_fixed()+
geom_abline(slope = 1 ,intercept = 100) + # add identity line
theme(
panel.background = element_blank(),
axis.title.x = element_text(size =18, face = 'bold'),
axis.title.y = element_text(size =18, face = 'bold'),
panel.border = element_rect(size = 2, fill = NA),
axis.text.x = element_text(size = 14, face ='bold'),
axis.text.y = element_text(size = 14, face ='bold')) +
xlab('100% - Specificity') +
ylab('100% - Sensitivity')
I got this:
But i need to change at free will my axes so they are in probabilities (100 -> 1, 50 -> .5 etc), and my X axis is inverted so 100 -> 0, and 0 -> 100. I give an example, i know i can just change my axis title so its technically correct, but i would want to know if i can change them. And if i could just put the ticks in every side of the plot frame that would be great :D. ¿How could i change my axes?

Yes you can definitely change your axis. It may give a warning because the ggroc() function already reversed the x-axis, but that is not a problem.
Most of the adjustments happen in the scales, a couple of points:
You can change the labelling by providing a custom function to the labels argument, if they underlying data was in percentage space instead of probability space
You can add a secondary axis with identity transformation ~ .x to have tickmarks appear in the top and on the right.
You can set expand to c(0,0) to not have any whitespace padding around the axes. I saw your example didn't have it, so I replicated that.
Lastly, in the theme, you can set the axis tick lengths of the secondary axis to a negative unit, to have the ticks point inward, like the example you gave.
I've not included all your theme settings that were not necessary to demonstrate this.
ggroc(roc.ob) +
coord_fixed()+
geom_abline(slope = 1 ,intercept = 100) + # add identity line
scale_x_continuous(trans = "reverse", name = "100% - Specificity",
labels = function(x){format(x/100)},
sec.axis = sec_axis(~ .x, labels = NULL),
expand = c(0,0)) +
scale_y_continuous(name = "100% - Sensitivity",
labels = function(x){format(x/100)},
sec.axis = sec_axis(~ .x, label = NULL),
expand = c(0,0)) +
theme_bw() +
theme(axis.ticks.length = unit(5, "pt"),
axis.ticks.length.x.top = unit(-5, "pt"),
axis.ticks.length.y.right = unit(-5, "pt"),
panel.grid = element_blank())

Related

Make X-Axis Lables, value labels and other axis and labels bold in Ggplot2

I work inside a research environment and I can't copy paste the code I used there, but I have previously generated this plot, and have been helped by various people in labelling it with the count number. The problem arises when I screenshot the plot from inside the research environment, and the legends are illegible. I am hoping I can address this by making the labels (including the X-axis label) all bold.
I used some mock-data outside the environment and this is what I have so far.
library(ggplot2)
library(reshape2)
md.df = melt(df, id.vars = c('Group.1'))
tmp = c("virginica","setosa","versicolor")
md.df2 = md.df[order(match(md.df$Group.1, tmp)),]
md.df2$Group.1 = factor(as.character(md.df2$Group.1), levels = unique(md.df2$Group.1))
ggplot(md.df2, aes(x = Group.1, y = value, group = variable, fill = variable)) +
geom_bar(stat="identity",color='black', position = "dodge") +
xlab('Species') + ylab('Values') + theme_bw()+
ylim(0,8)+
theme(text = element_text(size=16),
axis.text.x = element_text(angle=0, hjust=.5),
plot.title = element_text(hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5))+
ggtitle("Order variables in barplot")+
geom_text(aes(label=value), vjust=-0.3, size=4, # adding values
position = position_dodge(0.9))+ element_text(face="bold")
I need to make the labels onto bold, and the element_text isn't working mainly because I am probably using it in the wrong way. I'd appreciate any help with this.
An example of this plot which I haven't been able to find mock data to re-create outside the environment, have asked a question about in the past, is the one where the axis ticks also need to be made bold. This is because the plot is illegible from the outside.
I've tried addressing the illegibility by saving all my plots using ggsave in 300 resolution but it is very illegible.
I'd appreciate any help with this, and thank you for taking the time to help with this.
As I mentioned in my comment to make the value labels bold use geom_text(..., fontface = "bold") and to make the axis labels bold use axis.text.x = element_text(angle=0, hjust=.5, face = "bold").
Using a a minimal reproducible example based on the ggplot2::mpg dataset:
library(ggplot2)
library(dplyr)
# Create exmaple data
md.df2 <- mpg |>
count(Group.1 = manufacturer, name = "value") |>
mutate(
variable = value >= max(value),
Group.1 = reorder(Group.1, -value)
)
ggplot(md.df2, aes(x = Group.1, y = value, group = variable, fill = variable)) +
geom_col(color = "black", position = "dodge") +
geom_text(aes(label = value), vjust = -0.3, size = 4, position = position_dodge(0.9), fontface = "bold") +
labs(x = "Species", y = "Values", title = "Order variables in barplot") +
theme_bw() +
theme(
text = element_text(size = 16),
axis.text.x = element_text(angle = 90, vjust = .5, face = "bold"),
plot.title = element_text(hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5)
)
In addition to #stefan 's answer, you can also set tick length and thickness like so:
## ... plot code +
theme(## other settings ...,
axis.ticks = element_line(linewidth = 5),
axis.ticks.length = unit(10, 'pt'))
However, the example "phenotype conditions" will probably remain hard to appraise, regardless of optimization on the technical level. On the conceptual level it might help to display aggregates, e. g. condition counts per Frequency and supplement a textual list of conditions (sorted alphabetically and by Frequency, or the other way round) for those readers who indeed want to look up any specific condition.

Legend inscription above the legend

I have a rather specific problem for which I am currently looking for a solution and cannot find one.
I would like to create a legend with ggplot where the caption of the legend is below the legend - I don't know how to explain it better. I'm sure the following pictures will help:
How I would like the legend to be:
How the legend is current:
I draw the plot at the end via cowplot on a background (draw_plot), so there is also the possibility of drawing the legend "artificially" over the diagram (draw_text). However, I would have to manage to underline the text - and with the correct linetype (see diagram below). This would actually be my preferred variant - but I have no clue how this could work.
I provide you with the code for the plot and for the character on the background.
I am curious to see if anyone can find a solution! :)
Thank you and best regards
The whole Diagramm:
The ggplot-code (shortened):
colors <- c("#ff9a00","#ff9a00")
PlotLine <- ggplot(pp, aes(x, y, color = id, linetype = id))+
theme(legend.direction="horizontal"
)+
geom_path(size=1.25) +
scale_x_datetime(date_labels = "%Y", breaks = scales::pretty_breaks(n = 3), expand = expansion(mult = c(0.02, 0.03)))+
scale_color_manual(labels = paste("<span style='color:",
colors,
"'>",
unique(c(Nutzer1, Nutzer2)),
"</span>"),
values = colors)+
scale_linetype_manual(labels = paste("<span style='color:",
colors,
"'>",
unique(c(Nutzer1, Nutzer2)),
"</span>"),
values=c("solid","dotted"))+
xlab("")+
ylab("")+
theme(axis.text.x = element_text(size= 10, colour = "black", margin = margin(t = 10, b = -5)))+
theme(axis.text.y = element_blank(), legend.text = element_markdown(size = 8))+
labs(color=' ',linetype=' ')
cowplot-code (shortend):
Ausgabe <- ggdraw() +
draw_plot(PlotLine, width = 0.6, height = 0.18, x = 0.345, y = 0.094)
Data for the Lineplot:
The variables for "Nutzer1" and "Nutzer2" can be filled with anything. Sadly the referred dataframe "pp" is too long to export and post. But i guess any dummy data should do it ;)
Inside your scale_color_manual() add an argument about the "guide":
scale_color_manual(labels = paste("<span style='color:",
colors,
"'>",
unique(c(Nutzer1, Nutzer2)),
"</span>"),
values = colors,
guide = guide_legend(
direction = "horizontal",
label.position = "top"))
This will specify that your label should be on top of the key rather than to the right as it defaults.

Why is the resolution on my geom_points so poor

I came across an alternative to grouped bar charts in ggplot that Rebecca Barter posted on her blog and wanted to give it a try. It produces a slick Cleveland dot plot:
The code for my attempt follows:
ggplot() +
# remove axes and superfluous grids
theme_classic() +
theme(axis.ticks.y = element_blank(),
text = element_text(family = "Roboto Condensed"),
axis.text = element_text(size = rel(1.5)),
plot.title = element_text(size = 30, color = "#000000"),
plot.subtitle = element_text(size = 15, color = "#Ec111A"),
plot.caption = element_text(size = 15, color = "grey25"),
plot.margin = margin(20,20,20,20),
panel.background = element_rect(fill = "white"),
axis.line = element_blank(),
axis.text.x = element_text(vjust= + 15)) +
# add a dummy point for scaling purposes
geom_point(aes(x = 15, y = P),
size = 0, col = "white") +
# add the horizontal discipline lines
geom_hline(yintercept = 1:9, color = "grey80") +
# add a point for each male success rate
geom_point(aes(x = Male, y = P),
size = 15, col = "#00b0f0") +
# add a point for each female success rate
geom_point(aes(x = Female, y = P),
size = 15, col = "#Ec111A") +
geom_text(aes(x = Male, y = P,
label = paste0(round(Male, 1))),
col = "black", face="bold") +
# add the text (%) for each female success rate
geom_text(aes(x = Female, y = P,
label = paste0(round(Female, 1))),
col = "white", face="bold") +
# add a label above the first two points
geom_text(aes(x = x, y = y, label = label, col = label),
data.frame(x = c(21.8 - 0, 24.6 - 0), y = 7.5,
label = c("Male", "Female")), size = 6) +
scale_color_manual(values = c("#Ec111A", "#00b0f0"), guide = "none") +
# manually specify the x-axis
scale_x_continuous(breaks = c(0, 10, 20, 30),
labels = c("0%","10%", "20%", "30%")) +
# manually set the spacing above and below the plot
scale_y_discrete(expand = c(0.15, 0)) +
labs(
x = NULL,
y = NULL,
title= "Move Percentage By Gender",
subtitle = "What Percentage Of Moves Are Tops",
caption = "Takeaway: Males have fewer Tops and more Xs compared to Females.")
But my plot has very jagged (poor resolution points) and I can't figure out what's the cause.
Has anyone come across this problem and know how to fix it?
Saving and resolution depends on how you save and your graphics device. In other words... how are you saving your plot? Since it depends so much on your personal setup and parameters, your mileage will vary. One of the more dependable ways of saving plots from ggplot2 in R is to use ggsave(), where you can specify these parameters and maintain some consistency. Here is an example plot code:
ggplot(mtcars, aes(disp, mpg)) +
geom_point(size=10, color='red1') +
geom_text(aes(label=cyl), color='white')
This creates a plot similar to what you show using mtcars. If I copy and paste the graphic output directly from R or use export (I'm using RStudio) this is what you get:
Not sure if you can tell, but the edges are jagged and it does not look clean on close inspection. Definitely not OK for me. However, here's the same plot saved using ggsave():
ggsave('myplot.png', width = 9, height = 6)
You should be able to tell that it's a lot cleaner, because it is saved with a higher resolution. File size on the first is 9 KB, whereas it's 62 KB on the second.
In the end - just play with the settings on ggsave() and you should find some resolution that works for you. If you just input ggsave('myplotfile.png'), you'll get the width/height settings that match your viewport window in RStudio. You can get an idea of the aspect and size and adjust accordingly. One more point - be cautious that text does not scale the same as geoms, so your circles will increase in size differently than the text.

How do I specify the line colours in geom_step()?

What is the command for specifying the line colours in a ggplot using geom_step()?
The default colours are working fine, I just want to alter them to my preferred colours.
I have two groups, and my ggplot code starts:
ggplot(WomenAgeComparison, aes(x=IntegerAge, y=CumAgePercent, colour=DataSource)) +
geom_step()
The two groups plot fine. Everything works fine except for changing the line colours.
I have tried:
scale_color_manual(values=c("mediumorchid2",'blue'))
which gave the error
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
and didn't override the existing colours.
I also tried
scale_color_continuous(values=c("mediumorchid2",'blue'))
which gave the error
Error in continuous_scale(aesthetics, "gradient", seq_gradient_pal(low, :
unused argument (values = c("mediumorchid2", "blue"))
The example of two colours on this page used two separate geom_step() lines. Surely there is an easier way?
What is the command to use? Is there a scale_color command to use, or should it be specified in the aesthetics bracket? If the latter, how do I do that?
Updated to show full ggplot code:
ggplot(WomenAgeComparison, aes(x=IntegerAge, y=CumAgePercent, colour=DataSource)) +
geom_step() +
scale_color_manual(values=c("mediumorchid2",'blue')) +
xlab("Age (years)") + ylab("Cumulative proportion") +
scale_x_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 20), expand = c(0, 0)) +
scale_y_continuous(limits = c(0,1), breaks = seq(0, 1, by = .2), expand = c(0, 0)) +
scale_color_discrete(name = "Data source", labels = c("Synthetic data\nestimates", "Timaru Data\nrandom rounded\ncounts")) +
theme(legend.title = element_text(size = 15),
legend.text = element_text(size = 10),
legend.key.height=unit(1.5, "cm"),
axis.text = element_text(size = 10),
axis.title = element_text(size = 15))
I have the scale_color_discrete only to put in the text I want into the legend title and text. I tried to use the theme element_text options to do it instead, and couldn't get that to work.

How to manually edit a grid.arrange, ggplot_gtable and facet?

I'm ploting a Hydrograph but I additionally use facet_grid in R because I have objects with common features.
But when I use facet_grid the plot gets distorted, as shown in the figure below. How can I randerize this?
Note that it is not aligned properly, the scale of the y axis is scrambled, etc.
Among the adjustments I tried, I realized that it is possible to greatly improve this plot. I've created an image based on the above plot, some other attempts on how I'm trying and making some adjustments to paint to demonstrate what I'm trying to do.
Here's my code:
library(ggplot2)
library(grid)
library(gridExtra)
g1 <- ggplot(data_cet,
aes(x = Periodo,
y = Ind_plu)) +
geom_bar(stat = 'identity',
fill = "blue",
position = position_dodge()) +
ylab("Precip.") +
scale_y_reverse(labels = scales::comma) +
theme_bw() +
theme(axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank())
g2 <- ggplot(data_cet,
aes(x = Periodo,
y = Nivel,
colour = Bomba)) +
geom_line(aes(group = 1)) +
scale_color_manual(values = c("#0B775E", "#35274A", "#F2300F")) +
labs(colour = "Status CMB") +
facet_grid(data_cet$arranjo + data_cet$Bacia ~.) +
scale_x_date(breaks = datebreaks_m,
labels = date_format("%b/%y")) +
xlab('Período') + ylab('% Nível') +
theme_bw() +
theme(axis.text.x = element_text(face = "plain",
color = "black",
angle = 90),
axis.text.y = element_text(face = "plain",
color = "black"),
legend.title = element_blank(),
strip.background = element_blank(),
legend.position = "bottom")
g1 <- ggplot_gtable(ggplot_build(g1))
g2 <- ggplot_gtable(ggplot_build(g2))
maxWidth = unit.pmax(g1$widths[2:3], g2$widths[2:3])
g1$widths[2:3] <- maxWidth
g2$widths[2:3] <- maxWidth
plot_hyd <- grid.arrange(g1, g2, ncol = 1, heights = c(1, 3))
ggsave(file = "plot_hyd4.pdf", plot_hyd)
My dataset is too large, my apologize for not showing the dataset and dput().
You could add a widths = c(0.9, 1) to grid.arrange (fiddle with the first number some) to get your graphs to line up along the right side.
Otherwise, ggsave your file to a larger pdf. Your element_text objects, such as the legend, are absolute sizes, so if you scale up the pdf dimensions your graphs will look larger by comparison.
The exact values of widths and ggsave(width, height) are going to depend on you data, and unfortunately will take some trial and error. If you're using something like RStudio, I suggest fiddling with the grid.arrange call and finding the widths argument you like before calling ggsave. When you are ready to experiment with different ggsave width and height arguments, run it at a lower dpi the first few times so it processes more quickly.
Note that since you haven't included your data, I haven't tried to recreate this problem - this is just how I've solved this kind of issue in the past. If these suggestions don't work for you, let me know and I can use some built-in datasets to find another solution
Following the logic of the #Pintintended tip for the code. I adopted the layout_matrix argument.
>
plot_hyd <- grid.arrange(g1, g2,
layout_matrix = rbind(c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,NA),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),
c(2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)))
#ggsave(file="plot_hyd4.jpeg",plot_hyd,width=13,height=16,dpi=200)

Resources