Add offset label to ggplot histogram - r

I wish to add a label to one specific bar of a histogram, but off to the side, not above. Like this:
I'm unsure as to how to ONLY label the red bar nor how to offset the label with an arrow.
Code
library(tidyverse)
tree_df <- tibble (
rank = c(1, 2, 3, 4, 5),
name = c("oak", "elm", "maple", "pine", "spruce"),
freq = c(300, 50, 20, 10, 5)
)
bar_colour <- c(rep("black", 4), rep("red", 1))
last_bar <- tree_df[5,]
ggplot(data = tree_df, aes(x = reorder(row.names(tree_df), freq), y = freq)) +
geom_col(fill = bar_colour) +
geom_label(data = tree_df, label = c("Norway"))

If this is just a one-off and you're OK specifying the label position manually, you can use annotate:
ggplot(data = tree_df, aes(x = reorder(row.names(tree_df), freq), y = freq)) +
geom_col(fill = bar_colour) +
annotate(geom = "segment", x = 4, xend = 4.5, y = 250, yend = 250,
arrow = arrow(length = unit(0.03, "npc"))) +
annotate(geom = "label", x = 4, y = 250, label = "Norway")
Result:

Related

How can I add a mean bar and a jitter to my dot plots?

I am trying to compare data from three groups and I would like to have a mean bar on every group and some jitter.
first <- c(1, 1.2, 2, 3, 4)
second <- c(5, 6, 7, 8, 9)
third <- c(10, 16, 17, 18, 19)
df <- data.frame(Value = c(first,second),
Cat = c(rep("first",length(first)), rep("second",length(second))),
xseq = c(seq_along(first),seq_along(second)))
library(ggplot2)
ggplot(df, aes(x = Cat, y = Value, color = Cat)) + geom_point()+xlab("")
df <- data.frame(Value = c(first,second, third),
Cat = c(rep("first",length(first)),
rep("second",length(second)),
rep("third",length(third))),
xseq = c(seq_along(first),
seq_along(second),
seq_along(third)))
library(ggplot2)
ggplot(df, aes(x = Cat, y = Value, color = Cat)) + geom_point()+xlab("")
Something like this?
library(ggplot2)
ggplot(df, aes(x = Cat, y = Value, color = Cat)) +
geom_errorbar(stat = "summary", width = 0.1, color = "black", alpha = 0.5) +
stat_summary(geom = "point", fun = mean, color = "black") +
geom_point(position = position_jitter(width = 0.1), shape = 18, size = 4) +
scale_color_brewer(palette = "Set2") +
theme_light(base_size = 16)

Create a special Radial bar chart (race track plot)

I was able to replicate another good answers here to create a basic radial plot, but can anyone give me any clue of others functions/parameters/ideas on how to convert the basic one to something similar to this :
You could get pretty close like this:
df <- data.frame(x = c(10, 12.5, 15), y = c(1:3),
col = c("#fcfbfc", "#fbc3a0", "#ec6f4a"))
library(ggplot2)
ggplot(df, aes(x = 0, xend = x, y = y, yend = y, color = col)) +
geom_hline(yintercept = c(1:3), size = 14, color = "#dfdfdf") +
geom_hline(yintercept = c(1:3), size = 13, color = "#f7f7f7") +
geom_segment(color = "#bf2c23", size = 14, lineend = 'round') +
geom_segment(size = 13, lineend = 'round') +
scale_color_identity() +
geom_point(aes(x = x - 0.03 * y), size = 5, color = "#bf2c23",
shape = 21, fill = 'white') +
geom_point(aes(x = x - 0.03 * y), size = 2, color = "#bf2c23",
shape = 21, fill = 'white') +
scale_y_continuous(limits = c(0, 4)) +
scale_x_continuous(limits = c(0, 20)) +
coord_polar() +
theme_void()
Here's a start. Are there particular aspects you're trying to replicate? This is a fairly customized format.
df <- data.frame(type = c("on", "ia", "n"),
radius = c(2,3,4),
value = c(10,21,22))
library(ggplot2); library(ggforce)
ggplot(df) +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value),
size = 17, lineend = "round", color = "#bb353c") +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value, color = type),
size = 16, lineend = "round") +
geom_label(aes(radius, y = 30,
label = paste(type, ": ", value)), hjust = 1.8) +
scale_x_continuous(limits = c(0,4)) +
scale_y_continuous(limits = c(0, 30)) +
scale_color_manual(values = c("on" = "#fff7f2",
"ia" = "#f8b68f",
"n" = "#e4593a")) +
guides(color = "none") +
coord_polar(theta = "y") +
theme_void()

Cleanest way to add second legend for geom_segment based on color using ggplot2

library(ggplot2)
library(scales)
df = data.frame(Type = rep(c('A', 'B'), 250), Index = seq(500), Value = cumsum(rnorm(500)))
colors = hue_pal()(3)
labels = c('Alpha', 'Beta', 'Gamma')
ggplot(df, aes(Index, Value)) +
geom_line(aes(color = Type)) +
geom_segment(x = 200, xend = 300, y = -8, yend = -8, color=colors[1]) + # Label as "Alpha"
geom_segment(x = 400, xend = 500, y = -4, yend = -4, color=colors[1]) + # Label as "Alpha"
geom_segment(x = 0, xend = 100, y = 0, yend = 0, color=colors[2]) + # Label as "Beta"
geom_segment(x = 100, xend = 200, y = 4, yend = 4, color=colors[3]) + # Label as "Gamma"
geom_segment(x = 300, xend = 400, y = 8, yend = 8, color=colors[3]) # Label as "Gamma"
The code above produces the output below
I would like to add a second legend, with the title "Classification" and the entries "Alpha" "Beta" and "Gamma" corresponding to the three colors of the horizontal segments. The answer to Adding a legend entry for geom_segment suggests using scale_fill_manual but it has no effect. I am hoping there is a clean way to do this in R.
It's not particularly "clean", but I can't think of a better way of doing it:
library(tidyverse)
df = data.frame(Type = rep(c('A', 'B'), 250), Index = seq(500), Value = cumsum(rnorm(500)))
scales::hue_pal()(3)
#> [1] "#F8766D" "#00BA38" "#619CFF"
seg_df <- data.frame(x = c(200, 400, 0, 100, 300),
xend = c(300, 500, 100, 200, 400),
y = c(-8, -4, 0, 4, 8),
yend = c(-8, -4, 0, 4, 8),
col = factor(c("#F8766D", "#F8766D", "#00BA38",
"#619CFF", "#619CFF"),
labels = c("Alpha", "Beta", "Gamma")))
ggplot(df, aes(Index, Value)) +
geom_line(aes(col = Type), show.legend = TRUE) +
geom_segment(data = seg_df, aes(x = x, xend = xend,
y = y, yend = yend,
fill = col),
color = c("#F8766D", "#F8766D", "#00BA38",
"#619CFF", "#619CFF")) +
scale_fill_manual("Classification",
values = c("Alpha", "Beta", "Gamma"),
guide = guide_legend(override.aes = list(
colour = c("#F8766D", "#00BA38", "#619CFF"))))
I am interested to see if someone else can come up with an easier/cleaner method.

How to animate the axis label using `gganimate`?

I am actually very amazed to see I cannot quickly find a guide to how to do this. Here is an example:
library(ggplot2)
library(gganimate)
library(data.table)
library(magrittr)
dt <- lapply(seq(10), function(i){
mean = i
label = paste0("T = ", i)
dt = data.table(x = seq(0, 50, length.out = 100))
set(dt, j = "y", value = dt[, dlnorm(x, meanlog = log(mean), sdlog = 0.2)])
set(dt, j = "frameN", value = i)
return(dt)
}) %>% rbindlist
print(dt)
p <- ggplot(dt, aes(x = x, y = y)) +
geom_line() +
scale_x_continuous(name = "x", breaks = c(0, 1)) +
transition_manual(frameN)
animate(p)
I want the breaks and labels of scale_x_continuous to follow my own definitions:
arr_breaks <- c(1, 3, 2, 4, 3, 5, 4, 6, 5, 7)
arr_labels <- paste0(seq(10, 100, 10), " kg")
And then
breaks = arr_breaks[1], labels = arr_labels[1] for frame 1
breaks = arr_breaks[2], labels = arr_labels[2] for frame 2
...
breaks = arr_breaks[10], labels = arr_labels[10] for frame 10
No matter how I do it I got errors. Any idea?
As #z-lin noted, gganimate is not currently set up (to my knowledge) to animate scales with different breaks. The effect could be closely approximated using geoms, and with some more work you could probably make an exact visual match to a changing scale.
breaks_df <- data.frame(
frameN = c(1:10),
arr_breaks = c(1, 3, 2, 4, 3, 5, 4, 6, 5, 7),
arr_labels = paste0(seq(10, 100, 10), " kg")
)
p <- ggplot(dt, aes(x = x, y = y)) +
geom_segment(data = breaks_df, color = "white",
aes(x = arr_breaks, xend = arr_breaks,
y = -Inf, yend = Inf)) +
geom_text(data = breaks_df, vjust = 3, size = 3.5, color = "gray30",
aes(x = arr_breaks, y = 0, label = arr_labels)) +
geom_line() +
scale_x_continuous(name = "x", breaks = c(0)) +
coord_cartesian(clip = "off") +
transition_manual(frameN)
animate(p, width = 600, height = 250)

Connect line through facet_wrap in ggplot

The question relates to this: Line graph customization (add circles, colors), but since I got a new task, I created a new question.
So again my data frame is the same as in the question I've posted in a link. With code below and (little of my own modification) that was given to me by #beetroot
value <- c(9, 4, 10, 7, 10,
10, 10, 4, 10,
4, 10, 2, 5, 5, 4)
names <- c("a","b",
"c","d","e",
"f", "g","h",
"i","j","k","l",
"m","n","p")
df <- data.frame(value, names)
df$names <- as.character(df$names)
df$part <- rep(c("part3", "part2", "part1"), each = 5)
library(dplyr)
library(tidyr)
df2 <- df %>%
group_by(part, names) %>%
expand(value = min(df$value):max(df$value))
p <- ggplot() +
geom_point(data = df2, aes(x = value, y = names),
shape = 1) +
geom_point(data = df, aes(y = names, x = value, group = 1),
colour = I("red"), shape = 21, lwd = 3, fill = "red") +
geom_line(data = df, aes(y = names, x = value, group = 1),
group = I(1),color = I("red")) +
theme_bw() +
facet_wrap(~part, ncol = 1, scales = "free_y")
p + theme(strip.background = element_rect(fill="dodgerblue3"),
strip.text.x = element_text(colour = "white"))+xlab("") +ylab("")
df <- data.frame(value, names)
df$names <- as.character(df$names)
I get this output:
But now I would like to connect lines through (PART1, PART2 and PART3) so that my output would look like:
I used black color of a line just it will be more visible that I would like to connect this parts with lines.
Although I am not completely satisfied I've found solution. I computed the bounding box.
Firstly I removed facet_wrap(~part, ncol = 1, scales = "free_y") so my code looks like this:
p <- ggplot() +
geom_point(data = df2, aes(x = value, y = names),
shape = 1) +
geom_point(data = df, aes(y = names, x = value, group = 1),
colour = I("red"), shape = 21, lwd = 3, fill = "red") +
geom_line(data = df, aes(y = names, x = value, group = 1),
group = I(1),color = I("red")) +
theme_bw()
Then the trick was to create data frame and add the width and height of text directly:
# PART 1
TextFrame <- data.frame(X = 6, Y = 15.5, LAB = "PART 1")
TextFrame <- transform(TextFrame,
w = strwidth(LAB, 'inches') + 8,
h = strheight(LAB, 'inches') + 0.3
)
# PART 2
TextFrame.1 <- data.frame(X = 6, Y = 10.5, LAB = "PART 2")
TextFrame.1 <- transform(TextFrame.1,
w = strwidth(LAB, 'inches') + 8,
h = strheight(LAB, 'inches') + 0.3
)
# PART 3
TextFrame.2 <- data.frame(X = 6, Y = 4.5, LAB = "PART 3")
TextFrame.2 <- transform(TextFrame.2,
w = strwidth(LAB, 'inches') + 8,
h = strheight(LAB, 'inches') + 0.3
)
Then I've used geom_rectand geom_text to create the illusion I am after.
p + geom_rect(data = TextFrame, aes(xmin = X - w/2, xmax = X + w/2,
ymin = Y - h/2, ymax = Y + h/2), fill = "dodgerblue3") +
geom_text(data = TextFrame,aes(x = X, y = Y, label = LAB), size = 5) +
geom_rect(data = TextFrame.1, aes(xmin = X - w/2, xmax = X + w/2,
ymin = Y - h/2, ymax = Y + h/2), fill = "dodgerblue3") +
geom_text(data = TextFrame.1,aes(x = X, y = Y, label = LAB), size = 5) +
geom_rect(data = TextFrame.2, aes(xmin = X - w/2, xmax = X + w/2,
ymin = Y - h/2, ymax = Y + h/2), fill = "dodgerblue3") +
geom_text(data = TextFrame.2,aes(x = X, y = Y, label = LAB), size = 5)
And the output is:

Resources