How to highlight (bold or italic) specific labels using geom_label() - r

I am trying to highlight (either bold or italic) specific labels in a graph.
I am using geom_label but I don't know how to specify which groups should be highlighted.
Here is the data to build the table.
library(ggplot2)
library(dplyr)
library(ggalt)
library(cowplot)
library(tibble)
library(lubridate)
dates <- tribble( ~start_date, ~event, ~displ, ~model,
ymd(19680101), "No bold", 1, 'SP',
ymd(19820101), "Bold", 1, 'SP',
ymd(19800101), "No bold", 0.8, 'RCC',
ymd(20010101), "Bold", 0.8, 'RCC',
ymd(19740101), "No bold", -0.8,'OM',
ymd(19940101), "Bold", -0.8,'OM',
ymd(19560101), "No bold", -1,'SM',
ymd(20090101), "Bold", -1,'SM',
ymd(20010101), "No bold", 0.5,'US',
ymd(20090101), "Bold", 0.5,'US',
ymd(19890101), "Bold", -0.5,'LA')
Here is the function to plot the timeline.
shift_axis <- function(p, xmin, xmax, y=0){
g <- ggplotGrob(p)
dummy <- data.frame(y=y)
ax <- g[["grobs"]][g$layout$name == "axis-b"][[1]]
p + annotation_custom(grid::grobTree(ax, vp = grid::viewport(y=1, height=sum(ax$height))),
ymax=y, ymin=y) +
annotate("segment", y = 0, yend = 0, x = xmin, xend = xmax, size = 0.5,
arrow = arrow(length = unit(0.1, "inches"))) +
theme(axis.text.x = element_blank(),
axis.ticks.x=element_blank())
}
Finally, the graph where the labels go together in pairs (color coded).
vjust = ifelse(dates$displ > 0, -1.5, 1.5)
p1 <- dates %>%
ggplot(aes(start_date, displ)) +
geom_lollipop(point.size =1 ) +
#geom_text(aes(x = start_date, y = displ, label = event), data = data,
# hjust = 0, vjust = vjust, size = 4) +
geom_label(aes(x = start_date, y = displ, label = event, color=factor(model)),
data = data, hjust = 0, vjust = 0, size = 4) +
geom_point(aes(colour = factor(model)), size = 2) +
theme(axis.title = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.line = element_blank(),
axis.text.x = element_text(size = 12)) +
theme(axis.line = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank()) +
expand_limits(x = c(ymd(19500101), ymd(20210101)), y = 1.2) +
scale_x_date(breaks = scales::pretty_breaks(n = 9)) +
theme(legend.position = "none")
timeline <- shift_axis(p1, ymd(19500101), ymd(20210101))
timeline
So, I am trying to highlight the labels in "Bold" (either bold or italic) and the "No bold" leave them as they appear in the plot.
Thanks in advance.

Related

How to draw color line with size in R

I have a data with over 700 observations but below is a sample. Using geom_curve I want to make a plot where the line size(total_trips) corresponds to a color say 3 different colors. For instance between 0-100 (total_trips) can have a color of red
df <- data.frame(
origin_x = c(659627.8,642136.2,648774.7,659627.8,659627.8,658455.7,659627.8,659620.6,661641.8,656246.4),
origin_y = c(6473200,6473200,6462166,6473200,6473200,6467413,6473200,6467163,6479577,6487039),
dest_x = c(642136.2,659627.8,659627.8,648774.7,659620.6,659627.8,658455.7,659627.8,659627.8,659627.8),
dest_y = c(6456563,6473200,6473200,6462166,6467163,6473200,6467413,6473200,6473200,6473200
),
total_trips = c(4002,49878,2011,500,100,3000,2500,654,900,600))
I tried
ggplot() + geom_sf(data=shapefile, colour='grey', fill='grey93', size = 0.25) +
geom_curve(
data = df),
aes(
x = origin_x,
xend = dest_x,
y = origin_y,
yend = dest_y,
size = n,
colour= as.factor(c('red','blue'))),
curvature = 0.3
) + scale_alpha_continuous(range = c(0.09,1)) +
theme(
axis.title = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
plot.title = element_text(hjust = 0.5, size = 6),
plot.caption = element_text(hjust = 1),
plot.caption.position = 'plot',
axis.ticks = element_blank(),
panel.background = element_rect(fill = 'white'),
panel.grid = element_blank(),
plot.background = element_rect(color = NA, size = 0.5, fill=NA),
panel.border = element_rect(color = 'black', fill = NA, size=0.2) ,
legend.position = c(0.89,0.15),
legend.key.size = unit(0.4, 'cm'),
legend.text = element_text(size=7)
) +
annotation_scale(location = 'br', style = 'ticks') + coord_sf(crs=3301) +
annotation_north_arrow(location = 'tr', width = unit(0.20, 'cm'),height = unit(0.5,'cm'))
If I understand correctly - you want to change the colour of the line according to a categorised continuous variable (total_trips), we can do this:
Use cut to categorise the variable and give labels to the groups
Add this new variable to the aes(colour =.
library(dplyr)
library(ggplot2)
df <- df |> mutate(trips = cut(total_trips, c(0, 2000, 5000, 50000),
labels = c("0-2k", "2k-5k", "5k-50k")))
ggplot() +
geom_curve(data = df, aes(x = origin_x,
xend = dest_x,
y = origin_y,
yend = dest_y,
size = total_trips,
colour = trips
))
Output:
Not sure if this is what you want, though – your sample dataset doesn't contain the variable n that you mention in size = n, and you haven't provided us with shapefile.

How to align caption text with left bar in a bar chart?

I am trying to align the caption text in a bar chart, so that it will start at the same vertical margin as the left bar.
library(ggplot2)
library(tibble)
my_df <-
tibble::tribble(~response, ~estimate,
"little_bit", 0.353477,
"no", 0.307639,
"very", 0.338883)
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
ggtitle("do you like swimming with fish?") +
ylab("") +
labs(caption = "this is my caption") +
theme_minimal() +
theme(
axis.line.x = element_blank(),
axis.line.y = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.title = element_text(hjust = 0.5, size = 26),
axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
axis.title.x = element_blank(),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
plot.caption.position = "plot") ## <-- I thought this would help, but no...
Is there a way to align the caption such as the following?
To get your desired result set the caption position to "panel" and remove the expansion of the x-scale:
library(ggplot2)
library(tibble)
my_df <-
tibble::tribble(~response, ~estimate,
"little_bit", 0.353477,
"no", 0.307639,
"very", 0.338883)
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
ggtitle("do you like swimming with fish?") +
scale_x_discrete(expand = c(0, 0)) +
labs(caption = "this is my caption", y = NULL) +
theme_minimal() +
theme(
axis.line.x = element_blank(),
axis.line.y = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.title = element_text(hjust = 0.5, size = 26),
axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
axis.title.x = element_blank(),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
plot.caption.position = "panel")
Or, a very common workaround for those cases would be to annotate outside of the plot area. (I am using annotate(geom = "text",...) - you could also use geom_text, but you would only need a data frame for it.)
I personally prefer the annotate option as it is more versatile and generalisable for other purposes as well.
library(ggplot2)
my_df <-
tibble::tribble( ~response, ~estimate, "little_bit", 0.353477, "no", 0.307639, "very", 0.338883)
barwidth <- 0.9
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = barwidth, fill = "royalblue") +
annotate(
geom = "text",
x = 1 - barwidth / 2, hjust = 0, # that's the trick
y = -0.1, # play around with y. you could also set it relativ to your bar heights
label = "this is my caption"
) +
coord_cartesian(clip = "off", ylim = c(0, NA)) + # necessary to set axis limits and clip off to annotate beyond
ggtitle("do you like swimming with fish?") +
theme_minimal() +
theme(plot.margin = margin(b = 1, unit = "inch")) # margin randomly chosen. unfortunately also necessary

Aligning text on horizontal bar chart

I've come across several threads pointing out how to annotate bar charts, but I've tried a number of iterations of this code and can't seem to get the text left justified, starting at 0% on the x axis. I've tried to change hjust to "left", 0.95, and progressively larger numbers - none of them have the text tethered to the x origin.
dummy_data <- tibble(Proportion = c(0.87, 1),
`Person of Interest` = c("Person B", "Person A"))
dummy_data %>%
ggplot(aes(x = Proportion, y = `Person of Interest`,
fill = `Person of Interest`,
label = paste0(`Person of Interest`, "~", scales::percent(Proportion))))+
geom_col(width = 0.5) +
geom_text(position = position_dodge(width = .9), # move to center of bars
vjust = 0, # nudge above top of bar
hjust = "top",
size = 4.5,
colour = "white",
fontface = "bold") +
scale_x_continuous(labels = scales::percent,
limits = c(0, 1.01),
expand = c(0, 0)) +
ggthemes::theme_economist(horizontal = F) +
scale_fill_manual(values = alpha(c("black", "#002D62"), .5)) +
ggtitle("Lack of Skill") +
theme(title = element_text("Lack of Skill"),
plot.title = element_text(hjust = 0.5, face = "italic"),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_text(hjust = 0.25),
legend.position="none",
aspect.ratio = 1/3)
I've often found text data with ggplot maddening - a huge thanks to anyone willing to take a look.
Try this approach that is close to what you want. Your themes can be producing the issues with placing the labels:
#Code
dummy_data %>%
ggplot(aes(x=`Person of Interest`,
y=Proportion,
fill=`Person of Interest`,
label = paste0(`Person of Interest`, "~", scales::percent(Proportion))))+
geom_bar(stat = 'identity')+
geom_text(aes(y=0.13),
size = 4.5,
colour = "white",
fontface = "bold")+coord_flip()+
scale_y_continuous(labels = scales::percent,
limits = c(0, 1.01),
expand = c(0, 0)) +
ggthemes::theme_economist(horizontal = F) +
scale_fill_manual(values = alpha(c("black", "#002D62"), .5)) +
ggtitle("Lack of Skill") +
theme(title = element_text("Lack of Skill"),
plot.title = element_text(hjust = 0.5, face = "italic"),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_text(hjust = 0.25),
legend.position="none",
aspect.ratio = 1/3)
Output:

Creating a linear gauge in R with ggplot2: reducing barplot width

I have created a linear gauge in R to be displayed within PowerBI.
My only issue is that the width of the plot cannot be adjusted so I am getting the following:
(Plot is being rendered in PowerBI)
Whereas I would like to obtain the same graph but half the width.
I tried using width within geom_bar but it resizes the bar and the final output is the same.
Ideally, the bar would be half its current width (I am building this graph for a PowerBI report).
This is the code I used:
library(ggplot2)
scores = factor(c('Inadequate','Adequate','Fair','Good','Great','Excellent','Exceptional'),
levels = (c('Inadequate','Adequate','Fair','Good','Great','Excellent','Exceptional')),
ordered = TRUE)
x <- data.frame(points = rep(1,7), scores= scores)
x %>%
ggplot(aes(x=points, fill=scores)) +
geom_bar(position = "stack", show.legend = FALSE) +
geom_text(aes(label=scores, y = seq(from=0.5, to=6.5, by = 1)), label.size = 0.25)+
coord_flip() +
theme(panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
axis.text = element_blank()) +
geom_point(aes(x= 1.45, y=5), shape = 25, size=10, colour = "black", fill = "black") +
geom_point(aes(x= 0.55, y=3), shape = 24, size=10, colour = "black", fill = "black") +
geom_point(aes(x= 0.55, y=6), shape = 24, size=10, colour = "black", fill = "black") +
scale_fill_brewer(palette = "RdYlGn", direction = -1)
If simply resizing the Power BI visual is no option, you can use theme(plot.margin = unit(c(0, 0.2, 0, 0.2), "npc")) for increasing margins that ggplot draws around plot. Full code:
library(tidyverse)
scores = factor(c('Inadequate','Adequate','Fair','Good','Great','Excellent','Exceptional'),
levels = (c('Inadequate','Adequate','Fair','Good','Great','Excellent','Exceptional')),
ordered = TRUE)
x <- data.frame(points = rep(1,7), scores= scores)
x %>%
ggplot(aes(x=points, fill=scores)) +
geom_bar(position = "stack", show.legend = FALSE) +
geom_text(aes(label=scores, y = seq(from=0.5, to=6.5, by = 1)), label.size = 0.25)+
coord_flip() +
theme(panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_blank(),
axis.title = element_blank(),
axis.ticks = element_blank(),
axis.text = element_blank()) +
geom_point(aes(x= 1.45, y=5), shape = 25, size=10, colour = "black", fill = "black") +
geom_point(aes(x= 0.55, y=3), shape = 24, size=10, colour = "black", fill = "black") +
geom_point(aes(x= 0.55, y=6), shape = 24, size=10, colour = "black", fill = "black") +
scale_fill_brewer(palette = "RdYlGn", direction = -1) +
theme(plot.margin = unit(c(0, 0.2, 0, 0.2), "npc"))

ggplot2 bar chart tick position and custom legend issue

I have a ggplo bar chart like this
created from
library(lubridate)
library(ggplot2)
library(grid)
library(scales)
### Set up dummy data.
dayVec <- seq(ymd('2016-01-01'), ymd('2016-01-10'), by = '1 day')
dayCount <- length(dayVec)
dayValVec1 <- c(0,-0.25,0.15,0.3,0.4,0.10,0.17,0.22,0.50,0.89)
dayValVec2 <- c(0.15,0.2,-0.17,0.6,0.16,0.41,0.55,0.80,0.90,1.00)
dayValVec3 <- dayValVec2
dayDF <- data.frame(Date = rep(dayVec, 3),
DataType = factor(c(rep('A', dayCount), rep('B', dayCount), rep('C', dayCount))),
Value = c(dayValVec1, dayValVec2, dayValVec3))
p <- ggplot(dayDF,aes(Date, Value, colour = DataType)) +
theme_bw() +
ggtitle("Chart Title \n") +
scale_color_manual("",values = c("#033563", "#E1E2D2"),labels = c("xxx ", "yyy ")) +
geom_rect(aes(xmin = ymd(min(dayDF$Date)),
xmax = ymd('2016-01-06'),
ymin = -Inf,
ymax = Inf
), fill = "#E1E2D2", alpha = 0.1, colour = "#E1E2D2") +
geom_bar(stat = "identity", fill = "#033563", colour = "#033563") +
geom_hline(yintercept = 0, size = 1) +
scale_x_datetime(expand = c(0,0), labels = date_format('%b-%d'), breaks = date_breaks('1 day')) +
scale_y_continuous(expand = c(0,0), labels = percent, limits = c(min(dayDF$Value)*1.2, max(dayDF$Value)*1.2)) +
theme(axis.text.x = element_text(angle = 90),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_line(size = 0.5, colour = "black"),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
axis.text = element_text(size = 20, colour = "#033563"),
axis.title.x = element_text(hjust = 2),
plot.title = element_text(size = 40, face = "bold", colour = "#033563"),
legend.position = 'bottom',
legend.text = element_text(colour = "#033563", size = 20),
legend.key = element_blank(),
panel.border = element_rect(colour = "black", fill = NA, size = 1.5)
)
p
I have to problems now, first I want to have the goem_rect to start at 0 not centered at the first bar, the problem here seems to be the date x-axis. And secondly I would like to have a legend like this
at the bottom of the chart. I tried creating a dummy data series to get two legend entries, but it doesn't even show the legend. I would prefer if the legend could be manipulated without messing with the data. The 'yyy' legend entry should indicate what the shaded are represents. Thanks in advance, I am quite a newbie to ggplot2.
Here is a solution :
1st problem with geom_rect() due to format.
I prefered POSIXct, so I could easily modify the x axis :
geom_rect(aes(xmin = as.POSIXct("2015-12-31 12:00:00"),
xmax = as.POSIXct("2016-01-06 12:00:00"),
ymin = -Inf,
ymax = Inf,
fill = "#E1E2D2"),
color = "#E1E2D2", alpha = 0.1)
Tip : Start the "2015-12-31 12:00:00" to expand the geom_rect() and end the "2016-01-06 12:00:00" if you want to totaly fill the Jan 06.
Legend
You should use scale_fill_manual() instead of scale_color_manual()
And you have to put the fill argument inside aes for geom_rect() and geom_bar().
Code:
library(lubridate)
library(ggplot2)
library(grid)
library(scales)
dayVec <- seq(as.POSIXct('2016-01-01'), as.POSIXct('2016-01-10'), by = '1 day')
dayCount <- length(dayVec)
dayValVec1 <- c(0,-0.25,0.15,0.3,0.4,0.10,0.17,0.22,0.50,0.89)
dayValVec2 <- c(0.15,0.2,-0.17,0.6,0.16,0.41,0.55,0.80,0.90,1.00)
dayValVec3 <- dayValVec2
dayDF <- data.frame(Date = rep(dayVec, 3),
DataType = factor(c(rep('A', dayCount), rep('B', dayCount), rep('C', dayCount))),
Value = c(dayValVec1, dayValVec2, dayValVec3))
dayDF$Date = as.POSIXct(dayDF$Date)
p <- ggplot(dayDF,aes(Date, Value, colour = DataType)) +
theme_bw() +
ggtitle("Chart Title \n") +
geom_rect(aes(xmin = as.POSIXct("2015-12-31 12:00:00"),
xmax = as.POSIXct("2016-01-06 12:00:00"),
ymin = -Inf,
ymax = Inf,
fill = "#E1E2D2"),
color = "#E1E2D2", alpha = 0.1) +
geom_bar(aes(fill = "#033563"), color = "#033563", stat = "identity") +
geom_hline(yintercept = 0, size = 1) +
scale_x_datetime(expand = c(0,0), labels = date_format('%b-%d'), breaks = date_breaks('1 day')) +
scale_y_continuous(expand = c(0,0), labels = percent, limits = c(min(dayDF$Value)*1.2, max(dayDF$Value)*1.2)) +
theme(axis.text.x = element_text(angle = 90),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.major.y = element_line(size = 0.5, color = "black"),
axis.line = element_line(size = 1),
axis.ticks = element_line(size = 1),
axis.text = element_text(size = 20, color = "#033563"),
axis.title.x = element_text(hjust = 2),
plot.title = element_text(size = 40, face = "bold", colour = "#033563"),
legend.position = 'bottom',
legend.text = element_text(color = "#033563", size = 20),
legend.key = element_blank(),
panel.border = element_rect(color = "black", fill = NA, size = 1.5)
) +
scale_fill_manual("",values = c("#033563", "#E1E2D2"),labels = c("xxx ", "yyy "))
p
PS : I had to specify tz = "Europe/Paris" in scale_x_datetime(label = date_format()) to have correct dates, depending on location.

Resources