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.
Related
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.
I have a ggplot that I spent a fair amount of time formatting and getting the way I like it and discovered plotly/ggplotly to add in hovertext functionality, zoom, selection, etc. However, when I first tried ggplotly, the plot is very squashed especially on the x-axis (I'm looking at time-series data over the course of several days). I found the height/width parameters, defined them in a way that seemed to make sense, but on run all that seems to happen is the plot area gets larger, but the plot itself doesn't really fill the area defined by height and width. My code is below, along with screenshots of what I'm seeing. How do I get the plot to draw over the entire plotting area?
TimeSeries_plot <- ggplot(data = data_clean, aes(x = timestamp,
y = metrics_speed_download_mbps)) +
geom_line(color = '#9e2f7f') +
geom_point(aes(color=metrics_remote_location)) +
geom_hline(yintercept=DataAvg, color = "#414487") +
geom_text(aes(data_clean$timestamp[[150]],DataAvg, label = paste("average =", DataAvg, "Mbps")),
nudge_y = 30, color = "#414487", size = 5) +
scale_y_continuous(name = "Download Speed (Mbps)") +
scale_x_datetime(name = "Day in YYYY-MM-DD", date_breaks = "1 day", date_labels = "%Y-%m-%d",guide = guide_axis(angle=90)) +
geom_hline(yintercept = round(mean(data_clean$metrics_speed_download_mbps), 0), color = '#f1605d') +
geom_text(aes(data_clean$timestamp[[150]],round(mean(data_clean$metrics_speed_download_mbps)), label = paste("average =", round(mean(data_clean$metrics_speed_download_mbps)),"Mbps")),
nudge_y = 30, color = "#f1605d", size = 5) +
labs(title = "Figure 1: cURL 250M Download Test",
subtitle = "Boundary") +
scale_color_viridis_d() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90),
panel.background = element_rect(fill = '#fcfdbf', color = '#fcfdbf'),
panel.grid.major = element_line(color = '#feca8d', linetype = 'dashed'),
panel.grid.minor = element_line(color = '#feca8d', linetype = 'dotted')
)
ggplotly(TimeSeries_plot)
The ggplotly output looks like this:
ggplotly output with height and width defined:
Finally, ggplot2 output before adding ggplotly and what I'm trying to approximately get back to (using RMarkdown fig.height and fig.width parameters for the R chunk):
There are many questions out there pertaining to this topic, but none of the answers I have tried have worked for me so far.
I have a plot that is a heatmap with fill and alpha mapped to different values, i.e. different variables in my data create different colors and alpha values. I want to get a finished product here to see if this figure is worthwhile, so let's not discuss whether this is a good idea at the moment.
What I want to do is combine my fill and alpha legend such that I have the four different transparencies of blue, the four different transparencies of red, and for yellow. I can get those legends separately, or just one of them, but not two in one.
My best guess for code thus far has been
dummy <- data.frame(model=c(rep("X",23),rep("Y",23)),
longvarname=rep(c("CBH","NDMI","CovType","CH","CBD","NDVI_NF_750","Slope","TPI_Valley_1200", "TPI_Ridge_1200",
"TPI_Ridge_100","TPI_Valley_100", "TSHarv","Treat","RxBurn",
"TSTreat","TSRx","Deficit","SpecHumid","MaxRH","MinTemp","MaxTemp", "MaxGustDir", "MaxGustSpd"),2),
vargrp=rep(c(rep("Veg",6), rep("Topo",5), rep("Mgmt",5),rep("Clim",7)),2),
value=runif(46, min=0, max=1),
binary_slope=sample(c("negative","positive", "zero"), 46, replace=TRUE))
ggplot(dummy, aes(x=model, y=longvarname)) +
geom_tile(aes(fill=binary_slope, alpha=value))+
scale_alpha_binned(breaks=c(0.4, 0.6, 0.8, 1))+
facet_grid(vargrp~., scales='free_y', space="free_y")+
xlab("Model")+
ylab("Variable")+
scale_fill_manual(values=c("midnightblue","yellow1","red4"))+
# guides(fill=guide_legend(override.aes = list(fill=c(rep("#191970",4),
# rep("#FFEA00",4),
# rep("#8b0000",4)),
# alpha=rep(c(0.4,0.6,0.8,1),3))))+
theme(panel.background = element_blank(),
axis.text.x = element_text(angle = 45, hjust=1),
strip.text.y = element_blank(),
axis.ticks = element_blank())
The above code produces both legends which you can see in the example I attached. If you uncomment the guides() lines, the error I am getting is Error in [[<-.data.frame(*tmp*, i, value = c("#191970", "#191970", :
replacement has 12 rows, data has 3.
But most of my efforts have just resulted in only the fill legend at alpha=1. Another thought I had which I thought might get me there was in guides(), putting the alpha hex codes in front of each color hex code and then making alpha guide = "none", but no dice.
Thanks very much for your help!
Instead of making use of both fill and alpha one option would be to make use of just fill like so:
Add a column with your desired fill colors to your dataset using e.g. a left_join.
Manually compute your alpha levels using e.g. cut.
Adjust the transparency of th colors according to the alpha values using colorspace::adjust_transparency
Map the resulting colors on the fill aes and make use of scale_fill_identity. Add guide=guide_legend to get a legend.
library(ggplot2)
library(dplyr)
library(colorspace)
cols <- c(negative = "midnightblue", positive = "yellow1", zero = "red4")
cols <- tibble::enframe(cols, name = "binary_slope", value = "fill")
dummy <- left_join(dummy, cols, by = "binary_slope")
dummy <- mutate(dummy,
alpha = cut(value, breaks = c(0, 0.4, 0.6, 0.8, 1), labels = c(0.4, 0.6, 0.8, 1)),
alpha = as.numeric(as.character(alpha)),
fill = colorspace::adjust_transparency(fill, alpha)
)
ggplot(dummy, aes(x = model, y = longvarname)) +
geom_tile(aes(fill = fill)) +
scale_fill_identity(guide = guide_legend()) +
facet_grid(vargrp ~ ., scales = "free_y", space = "free_y") +
xlab("Model") +
ylab("Variable") +
theme(
panel.background = element_blank(),
axis.text.x = element_text(angle = 45, hjust = 1),
strip.text.y = element_blank(),
axis.ticks = element_blank()
)
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())
I am trying to insert a shape (and fill color) into a title/subtitle, but cannot find the syntax to do so:
library(tidyverse)
D <-diamonds %>% filter(color=="D") %>%sample_frac(0.1)
G <-diamonds %>% filter(color=="G") %>% sample_frac(0.1)
ggplot(D, aes(x=carat, y=price))+
geom_jitter(data=G)+geom_point(shape=6)+
geom_jitter(data=D)+geom_point(shape=22, fill='red')+
labs(title, "This is a title",
subtitle=
"D diamonds (insert shape 22 fill red) and G diamonds (shape 6 color black)",
caption = "what I want is to insert the shape and fill color into the (sub)title")
Suggestions? Annotate seem designed to work only in the plot-space.
A possible work-around from working with images is to use a legend to get the look you want. This involves first making a legend. I used the color aesthetic to make the legend, one for each points layer. The strings I give in aes will be the label legends.
I modify the legend via scale_color_manual. This involves getting the labels in the right order and setting the colors. In addition I use guide_legend options to move the labels to the left of the key boxes (they default to the right) and get the right shapes and fills for the points.
Then, in theme, the legend can be moved to the top left, the key boxes can be filled with white instead of grey and reduced in size, and the space around the legend can be reduced.
This all looks like:
ggplot(D, aes(x = carat, y = price))+
geom_jitter(data = G) +
geom_point(data = G, aes(color = "and G diamonds"), shape = 6) +
geom_jitter() +
geom_point(aes(color = "D diamonds"), shape = 22, fill='red') +
labs(title = "This is a title") +
scale_color_manual(name = NULL, values = c("black", "black"),
limits = c("D diamonds", "and G diamonds"),
guide = guide_legend(label.position = "left",
override.aes = list(shape = c(22, 6),
fill = c("red", "black")) ) ) +
theme(legend.direction = "horizontal",
legend.position = "top",
legend.justification = "left",
legend.key = element_rect(fill = "white"),
legend.key.size = unit(.5, "mm"),
legend.margin = margin(b = 0, 0, 0, 0) )
Starting in the current development version of ggplot2, ggplot2_2.1.0.9001, there is a legend.box.spacing option in theme to reduce the space between the plot and the legend. I thought legend.box.spacing = unit(2, "mm") looked pretty good.