Placing ggplot2 shape annotations into titles - r

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.

Related

making changes on boxplot objects

these are my codes:
ggplot(summer.months, aes(x = month, y = Temp_mean, linetype = position, color = canopy, fill = position)) +
geom_boxplot() +
theme_bw() +
ggtitle(" Temperature changes in elevated and lying deadwood in summer under different canopies") +
labs(y = "temperature values(C°)", x = "months") +
scale_fill_manual(values = c("white", "white", "green", "black"))
my professor said:
i have to put number of objects on the legend on the graph and put the legend on the upper right-hand corner of the graph & make the legend bigger.
put the months in a chronological order like 11,12,1,2,3,4.. ( put the names of the months in the graph instead of numbers)
i created a basic ggplot but the problem is i can´t do the changes that they want from me cuz the names and order of the objects are so in my excel data.
A dput(head(summer.months)) might be sufficient. Anyway, here's an example using internal dataset mpg for illustrating few adjustments:
library(tidyverse)
## changing variable for x-Axis into ordered factor - this is a bit of a workaround. If using dates,
## it is better to use datatype date and adjust axis labels accordingly
my_mpg <- mpg %>%
mutate(class = factor(class, levels = c("compact", "midsize", "suv", "2seater", "minivan", "pickup", "subcompact"), ordered = TRUE))
ggplot(my_mpg, aes(x = class, y = hwy, linetype = class, colour = fl, fill = drv)) +
geom_boxplot() +
scale_fill_manual(values = c("white", "white", "green", "black")) +
## using subtitle to add information about the dataset
labs(title = "title", subtitle = paste("#lines: ", nrow(mpg))) +
theme_bw() +
theme(legend.justification = "top", ## move legend to top
legend.text = element_text(size = 10), ## adjust text sizes in legend
legend.title = element_text(size =10),
legend.key.size = unit(20, "pt"), ## if required: adjust size of legend keys
plot.subtitle = element_text(hjust = 1.0)) ## shift subtitle to the right
You might find further hints in ggplot2 reference and the ggplot2 book.

Adding horizontal title/label to bar charts in ggplot R

is there a way to plot a bar graph in ggplot and group the bars accordingly using a horizontal line with label. It should look something like in the image below but for multiple groups and bars in one single graph only.
For context, I'm planning to group three bars for each horizontal label in one graph. For example, the first 3 bars would represent my control, the next three bars would be for treatment 1, the next three would be for treatment 2, and so on.
Let me know if you have a template for making such a graph. Thanks!
The default approach to achieve the kind of grouping would be via faceting, However, TBMK the default element_rect provided by ggplot2 does not offer the option to just draw a top line.
One option would be to create a custom theme element to achieve that. To this end I adapted the code for the default element_rect where I replaced the ´rectGrobby alinesGrob`.
Moreover, to also add the top lines for the axis labels I draw on ggh4x to add the axis labels via facets too. Doing so allows to use the custom theme element to add the top lines for the "axis labels" too (Of course would it be possible to create another custom theme element.).
Using mtcars as example data:
element_rect2 <- function(colour = NULL, size = NULL, linetype = NULL,
color = NULL, inherit.blank = FALSE) {
if (!is.null(color)) {
colour <- color
}
structure(list(
colour = colour, size = size,
linetype = linetype, inherit.blank = inherit.blank
),
class = c("element_rect2", "element_rect", "element")
)
}
element_grob.element_rect2 <- function(element, x = unit(c(0, 1), "npc"), y = unit(c(1, 1), "npc"),
colour = NULL, size = NULL, linetype = NULL, ...) {
gp <- grid::gpar(lwd = size, col = colour, lty = linetype)
element_gp <- grid::gpar(lwd = element$size, col = element$colour, lty = element$linetype)
gp <- modifyList(element_gp, gp)
grid::linesGrob(x, y - unit(gp$lwd, unit = "pt"), gp = gp, ...)
}
library(ggplot2)
library(ggh4x)
ggplot(mtcars, aes(factor(cyl))) +
geom_bar() +
scale_y_continuous(expand = expansion(mult = c(0, .05))) +
labs(x = NULL, y = NULL) +
facet_wrap2(am ~ cyl,
strip.position = "bottom", scales = "free_x",
strip = strip_nested(
background_x = list(
element_rect2(size = 2),
element_rect2(size = 2)
),
by_layer_x = TRUE
),
nrow = 1
) +
theme_minimal() +
theme(
panel.grid = element_blank(),
axis.line.y = element_line(size = .75, lineend = "square"),
axis.ticks.y = element_line(size = .75),
axis.text.x = element_blank(),
strip.placement = "outside"
)
You can use geom_bar() from the ggplot2 package to make similar looking bar plots.
library(ggplot2)
data(iris)
ggplot(iris, aes(x = Species, y = Petal.Length)) +
geom_bar(stat = "identity", fill = "black") +
theme_bw()

Adding visual embellishment in a custom ggplot theme

I'm currently prototyping custom ggplot themes for use within my organisation. Currently, the theme looks like this (using mtcars data):
I would like to add a solid-colored bar (in the org's primary color) underlining the chart title region to act as an easily scalable type of branding (rather than a jpeg logo which restricts the aspect ratio and size of the charts). I made a mockup of the effect I'm trying to achieve in paint:
I'm aware of annotate() but as far as I understand it that function only accepts arguments corresponding to x and y coordinates in the plotting area, so I don't know how to create an annotation that is bound to a point outside of the plotting area
I would use annotation_custom using a grid::linesGrob here. This allows you to place the line relative to the panel without having to use the plot limits, which can produce inconsistent results. It also allows the line to extend beyond the left and right limits of the plotting area.
Suppose your plot is created a bit like this:
library(ggplot2)
p <- ggplot(mpg, aes(displ, hwy, col = class)) +
geom_point() +
labs(title = "Test 1, theme 1", subtitle = "R default dataset",
caption = "Organization caption here",
y = "Fuel efficiency (mpg)",
x = "Engine displacement (litres)") +
scale_color_brewer(palette = "Set2", name = NULL) +
theme(panel.grid = element_line(color = "gray50"),
panel.border = element_rect(fill = NA),
legend.position = "top")
p
To add the line you can do:
p + coord_cartesian(clip = "off") +
annotation_custom(grid::linesGrob(
x = unit(c(-1, 2), "npc"), y = unit(c(1.2, 1.2), "npc"),
gp = grid::gpar(col = "orange2", lwd = 5)))
It is a bit hard without reproducible example, but you can use annotate with "segment" and define the x-values with Inf and the y-values with max(y) + some value depending on your theme layout like this:
library(ggplot2)
library(dplyr)
mtcars %>%
ggplot(aes(x = mpg, y = wt)) +
geom_point() +
annotate("segment", x = -Inf, xend = Inf, y = max(mtcars$wt) + 0.5, yend = max(mtcars$wt) + 0.5, colour = "orange", size = 2) +
coord_cartesian(clip = "off", ylim = c(min(mtcars$wt), max(mtcars$wt))) +
theme(plot.margin = unit(c(3,3,1,1), "lines"))
Created on 2022-07-27 by the reprex package (v2.0.1)

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.

Setting a legend in the center of a circular barplot (ggplot2)

I'm using this tutorial to create a circular barplot: https://www.r-graph-gallery.com/295-basic-circular-barplot.html
I want to create a legend in the middle of the barplot, where the white area is. However, so far i have only been able to add text in the middle. If i want to draw a small cube with the colour, it wraps itself around and i don't know how it uses the coordinates (i tried x = 0, y = 0 which gives the result below, they are always curved).
These are the two lines that i added:
geom_tile(aes(x = 1, y = 0, colour = "#EB5500"), width = 100, height = 100, inherit.aes = F) +
geom_text(x = 0, aes(y = -100, label = "test"), size = 4)
So that the full code now looks like this:
# Clear workspace
rm(list = ls())
# Libraries
library(tidyverse)
# Create dataset
data <- data.frame(
id=seq(1,60),
individual=paste( "Mister ", seq(1,60), sep=""),
value=sample( seq(10,100), 60, replace=T)
)
# Make the plot
p <- ggplot(data, aes(x=as.factor(id), y=value)) + # Note that id is a factor. If x is numeric, there is some space between the first bar
# This add the bars with a blue color
geom_bar(stat="identity", fill=alpha("blue", 0.3)) +
# Limits of the plot = very important. The negative value controls the size of the inner circle, the positive one is useful to add size over each bar
ylim(-100,120) +
# Custom the theme: no axis title and no cartesian grid
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-2,4), "cm") # This remove unnecessary margin around plot
) +
# This makes the coordinate polar instead of cartesian.
coord_polar(start = 0) +
geom_tile(aes(x = 1, y = 0, colour = "#EB5500"), width = 100, height = 100, inherit.aes = F) +
geom_text(x = 0, aes(y = -100, label = "test"), size = 4)
p
But this gives me an image that looks like this:
It seems that ggplot automatically adds a legend based on the grid that I added. That legend needs to be in the center, and it should be a legend for the blue bar chart instead of the grid. Is there a way to do this?
What I don't really get about your question is what is supposed to be in the legend. The idea of legends is that they explain a mapping (something inside aes()) so you usually want to have that in your data already:
library(tidyverse)
data <- data.frame(
id=seq(1,60),
individual=paste( "Mister ", seq(1,60), sep=""),
value=sample( seq(10,100), 60, replace=T),
colour = "test1" # added to have something to map to
)
Now you can map the fill aesthetic to the new column. To move the legend to the center you have to add legend.position = c(0.5, 0.5) to your theme.
p <- ggplot(data, aes(x=as.factor(id), y=value, fill = colour)) + # Note that id is a factor. If x is numeric, there is some space between the first bar
geom_bar(stat="identity") +
ylim(-100,120) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
legend.position = c(0.5, 0.5), # move legend to the center
plot.margin = unit(rep(-2,4), "cm") # This remove unnecessary margin around plot
) +
coord_polar(start = 0)
p
I chose test1 to show that anything can go into the data. To change the colour you have to define a manual (or other) scale:
p +
scale_fill_manual(values = alpha("blue", 0.3))
theme(legend.position = c(.5, .5)) center the legend to the plot.

Resources