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
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.
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
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:
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"))
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.