ggplot
Â
Date: 2024-05-01
R
version: 3.5.0
*Corresponding author: matthew.malishev [at] gmail.com
This document can be found at https://github.com/darwinanddavis/UsefulCode
Same deal as Useful Code 1 and 2 except just gglot
because it’s too difficult sifting through the other docs.
# option 1
<- p + labs(title = "Option 1") + theme_classic()
p1
p1
# option 2 with inputs to toggle
<- p + labs(title = "Option 2") + theme_bw() + theme(panel.border = element_blank(), panel.grid.major = element_blank(),
p2 panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"))
p2# alternative (after loading ggridges library) theme_ridges(grid=F,center_axis_labels = T)
<- function(bg) {
plot_it_now # bg = colour to plot bg
theme(panel.border = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_rect(fill = bg, colour = bg), plot.background = element_rect(fill = bg)) +
theme(axis.line = element_line(color = "white")) + theme(axis.ticks = element_line(color = "white")) +
theme(plot.title = element_text(colour = "white")) + theme(axis.title.x = element_text(colour = "white"),
axis.title.y = element_text(colour = "white")) + theme(axis.text.x = element_text(color = "white"),
axis.text.y = element_text(color = "white")) + theme(legend.key = element_rect(fill = bg)) +
theme(legend.title = element_text(colour = "white")) + theme(legend.text = element_text(colour = "white"))
}plot_it_now("black")
Ref: http://jcborras.net/carpet/visualizing-political-divergences-2012-local-elections-in-helsinki.html
<- function(d) {
hr.mass.plot <- ggplot(d, aes(HR, Mass, color = colfunc)) + geom_density_2d(data = d, aes(x = HR, y = Mass),
p stat = "density2d", position = "identity", color = adjustcolor("orange", alpha = 0.8), size = 1.5,
contour = T, lineend = "square", linejoin = "round")
<- p + geom_point(data = d, aes(x = HR, y = Mass), color = colfunc, fill = colfunc) + scale_color_manual(values = magma(8))
p <- p + scale_y_continuous(limits = c(-200, 200), name = "Mass lost (g)")
p <- p + scale_x_continuous(limits = c(0, 0.35), name = expression("Home range area (km^2)"))
p <- p + theme_classic()
p print(p)
}hr.mass.plot(d)
ggplot
when looping through for
loop
and saving to dirpdf("mypdf.pdf", onefile = T)
for (i in 1:3) {
par(bty = "n", las = 1)
grid.arrange(ggplot(data, aes(x = X, y = Y, fill = ..x..)) + geom_point() + labs(title = paste0("Title_",
+ xlab("X") + ylab("Y"))
i))
}# end loop
dev.off()
# geom_density_ridges() # scale = overlap
# geom_density_ridges(scale = 5, size=0.2,color='white', rel_min_height = 0.01,fill=col,alpha=0.5) +
# scale_fill_viridis option = 'magma', 'inferno','plasma', 'viridis', 'cividis'
ggplot
(melt
package)require(reshape2) # melt package
<- 10 # reps
nn <- data.frame(X = rep(LETTERS, nn), Y = sample(nn, replace = T), Z = rep(paste(LETTERS, "_", rnorm(1)),
mm
nn))# plot
<- melt(mm)
y_m head(y_m)
ggplot(data = y_m, aes(x = X, y = value, group = Z, colour = factor(value))) + geom_point(aes(size = value)) +
geom_line() + theme_classic()
= sample(100, 100)
xx = rnorm(100)
yy
<- bquote("Density = " ~ r[xy] ~ "and" ~ B^2 ~ +beta ~ alpha)
title1 ggplot() + geom_point(aes(x = xx, y = yy), color = xx) + labs(title = title1, xlab = title1, yab = title1,
colour = title1)
ggplot() + scale_color_manual(expression(atop("text", atop(textstyle(epsilon)))))
ggplot() + scale_color_manual(name = expression(atop("Productivity", atop(textstyle((mg ~ C ~ L^{
-1
~ d^{
} -1
# this is bracketed text
}) )))))
require(ggplot2)
= sample(100, 100)
xx = rnorm(100)
yy <- data.frame(X = xx, Y = yy)
df
ggplot(df) + geom_point(aes(xx, yy, size = 5), colour = xx, show.legend = F) + geom_text(aes(xx, yy,
label = xx), check_overlap = T, size = yy + 5) + theme_classic()
# add bg label
ggplot() + geom_line(aes(xx, yy, size = 5), colour = xx, show.legend = F) + geom_label(aes(xx, yy, label = xx),
size = yy + 5, color = yy + 5, fill = xx) + theme_classic()
Add text only to final point (plus other methods)
require(directlabels)
<- tibble("x" = sample(10,5),
df "y" = sample(10,5),
"label" = LETTERS[1:5])
ggplot() +
geom_point(data = df, aes(x,y)) +
geom_dl(aes(label = label),
method = list(
dl.trans(x = x + 0.3, y = y + 0), # expand x/y axis to fit in labels
list(dl.combine("first.points","last.points")), cex = 0.5 # add labels to first and last points
)+
) scale_x_continuous( ..., expand = c(0, 1.5))
# use ticks, not quotations
require(ggplot2)
<- data.frame(X = rnorm(1000), `Y col with spaces` = sample(1000, replace = T))
df
# incorrect y col, but doesn't throw error
ggplot(df, aes(X, "Y col with spaces")) + geom_line()
# same issue even when matching col name
ggplot(df, aes(X, "Y.col.with.spaces")) + geom_line()
# usable y col
ggplot(df, aes(X, Y.col.with.spaces)) + geom_line()
Code Meaning
%a Abbreviated weekday
%A Full weekday
%b Abbreviated month
%B Full month
%c Locale-specific date and time
%d Decimal date
%H Decimal hours (24 hour)
%I Decimal hours (12 hour)
%j Decimal day of the year
%m Decimal month
%M Decimal minute
%p Locale-specific AM/PM
%S Decimal second
%U Decimal week of the year (starting on Sunday)
%w Decimal Weekday (0=Sunday)
%W Decimal week of the year (starting on Monday)
%x Locale-specific Date
%X Locale-specific Time
%y 2-digit year
%Y 4-digit year
%z Offset from GMT
%Z Time zone (character)
require(nycflights13);require(dplyr);require(ggplot2)
%>% str
flights $time_hour %>% class # already posix
flights<- flights$time_hour %>% as.character() # convert posix to character
flights_mod
# turn into posix year month day hour minute second format
require(lubridate)
<- flights_mod %>% ymd_hms()
flights_mod %>% class
flights_mod
# make new df with fewer data
<- data.frame("Date"=flights_mod[1:100000],
df "Delay"=flights$arr_delay[1:100000])
ggplot(df, aes(Delay,Date)) + geom_tile() +
scale_y_datetime(date_breaks = "1 month",
date_minor_breaks = "1 week", # optional
date_labels = "%B %Y" # full month and year
+
) theme_classic()
gridExtra
require(gridExtra)
<- 100 # create sample
nn <- ggplot()+geom_point(aes(sample(nn,replace=T),rnorm(nn),size=runif(nn),color=rainbow(nn)),show.legend = F)+theme_classic()
p
# put plots into list
<- list(p,p,p,p)
ggplot_list
# 3 plots above, 1 below
grid.arrange(
grobs = ggplot_list, # list with ggplots or grobs
widths = c(1, 1, 1),
layout_matrix = rbind(c(1, 2, 3),
c(4, 4, 4))
)
# 3 plots above with first plot 2 plots wide
grid.arrange(
grobs = ggplot_list, # list with ggplots or grobs
widths = c(2, 1, 1), # widths (2,1,1) of total plots for each row (3)
layout_matrix = rbind(c(1, 2, 3),
c(4, 4, 4))
)
# 2 plots below with third plot 3 plots wide
grid.arrange(
grobs = ggplot_list, # list with ggplots or grobs
widths = c(2, 1, 1),
layout_matrix = rbind(c(1, 2, NA),
c(3, 3, 4))
)
Arranging multiplot panels
# https://patchwork.data-imaginist.com/articles/guides/assembly.html
# devtools::install_github('thomasp85/patchwork')
require(patchwork)
<- ggplot(mtcars) + geom_point(aes(mpg, disp, col = cyl), show.legend = F) + ggtitle("Plot 1") + theme_classic()
p1 <- ggplot(mtcars) + geom_point(aes(mpg, cyl, col = disp), show.legend = F) + ggtitle("Plot 2") + theme_classic()
p2
<- p1
p3 <- p2
p4
# 2 plots, 2 cols
+ p2 p1
# multi rows
| p2 | p3)/p4 # 3 plots top, 1 bottom (2 rows) (p1
/(p2 | p3) # 1 plot top, 2 bottom (2 rows) p1
# 2 plots, 2 rows and 2 cols
wrap_plots(p1, p2, p3, p4)
# 3 plots, 2 cols
<- p1 + p2
patch + patch p3
# non ggplot content eg. text
+ grid::textGrob("Some text") p1
+ gridExtra::tableGrob(mtcars[1:10, c("mpg", "disp")]) p1
# title, subs, and captions
<- (p1 + p2)/p3
patchwork + plot_annotation(title = "ttl", subtitle = "subttl", caption = "caption") patchwork
# set 'labs' arguments to same title as in 'scale_color_manual'
# legend values automatically matches arguments passed to colvec
# NB specifying the labels arg in scale_color_manual overrides labs
require(ggplot2)
<- data.frame(
snack_df "X"=sample(100,10,replace=F),
"Y"=sample(100,10,replace=F),
"Sum"=runif(10),
"Size"=rep(LETTERS[1:5],each=2)
)<- colorspace::sequential_hcl(length(unique(snack_df$Size)), "SunsetDark")
colvec <- "This is your legend"
legend_ttl <- unique(snack_df$Size) # not run
legend_pars
ggplot(snack_df,aes(X,Y)) +
geom_line(aes(group=Size,color=Size,linetype=Size),size=1) +
geom_point(aes(group=Size,color=Size,shape=Size),size=3) +
scale_color_manual(name=legend_ttl,
# labels = legend_pars, # this overrides labs
values = colvec) +
geom_text(aes(X,Y,
label=c(Size)
),check_overlap = T,
size=5,vjust=-1,hjust=1.2) +
labs(title="Plot title",x="X",y="Y",
# ----- these are the legend key arguments
colour=legend_ttl,
fill=legend_ttl,
linetype=legend_ttl,
shape=legend_ttl) + # check shape
theme_classic()
Option 1
# http://www.rebeccabarter.com/blog/2020-02-05_rstudio_conf/
require(tidyverse)
require(dplyr)
%>% head
midwest <- function(var1, var2) {
plotMidwestTidy ggplot(midwest) + geom_point(aes(x = {
{
var1
}y = {
},
{
var2
}# wrap vars in double curly braces
}
))
}
plotMidwestTidy(popdensity, poptotal) + theme_bw()
Option 2 Can’t use character class as user argument
require(ggplot2)
<- theme_classic()
my_theme <- "class"
colour_var <- "drv"
facet_var
ggplot(mpg) + geom_point(aes(displ, hwy, colour = colour_var)) + facet_wrap(vars(facet_var)) + my_theme
Placing .data
in front of your variables and wrapping
them with double square braces ‘[[]]’ solves this.
require(ggplot2)
<- theme_classic()
my_theme <- "class"
colour_var <- "drv"
facet_var
ggplot(mpg) + geom_point(aes(displ, hwy, colour = .data[[colour_var]])) + facet_wrap(vars(.data[[facet_var]])) +
+ ggtitle(paste0(colour_var, " vs ", facet_var)) my_theme
ggplot
objectsrequire(ggplot2)
<- F
cond1 <- T
cond2 <- ggplot(mtcars) + geom_point(aes(mpg, hp, size = 3), show.legend = F) + theme_classic()
p <- p + if (cond1 == T) {
p # execute condition 1 and add to plot
geom_line(aes(mpg, hp, size = 3), color = "red", show.legend = F)
}<- p + if (cond2 == T) {
p # execute condition 2 and add to plot
geom_line(aes(mpg, hp, size = 2), color = "blue", show.legend = F)
} p
Make calendar plot
require(sugrrants)
require(nycflights13)
<- flights
ff <- ff %>% mutate(date = flights$time_hour %>% as.Date())
ff <- frame_calendar(ff, x = distance, y = arr_delay, date = date, nrow = 4)
fdf <- ggplot(fdf) + geom_line(aes(x = .distance, y = .arr_delay, group = date)) + theme_void()
p %>% prettify() p
https://stackoverflow.com/questions/29803253/r-extracting-coordinates-from-spatialpolygonsdataframe
<- microbenchmark(raster::geom(atf_sp), ggplot2::fortify(atf_sp), spbabel::sptable(atf_sp), as.data.frame(as(as(atf_sp,
res "SpatialLinesDataFrame"), "SpatialPointsDataFrame")))
::autoplot(res) ggplot2
Flip axis directions
# rotate
print(p, vp = viewport(angle = -30))
+ coord_flip()
p + scale_y_reverse()
p graphics.off()
Reorder data within variables to have custom plot order
ggplot() + geom_bar(data = df, aes(year, value, fill = factor(var1, level = unique(var1)) # reorder to match order data is listed within variable
))
Match df column/variable to custom colour scale
require(colorspace)
<- sequential_hcl(d %>% pull(var1) %>% n_distinct(), "Tofino")
mycolors names(mycolors) <- d$var1 %>% unique %>% factor %>% levels
<- scale_colour_manual(name = "Title", values = mycolors)
custom_colors
ggplot() + geom_sf(data = d) + custom_colors # add scale
require(colorspace)
require(scales)
# match sequential colpal as sequential values in df
<- colorRampPalette(colors = c(col_low, col_high))
colv <- colv(d$value %>% length)
colpal $colpal <- colpal
d
# match sequential colpal to unique values in df var
<- sequential_hcl(d$value %>% length, "Sunset")
colpal <- col_numeric(palette = colpal, domain = d$value)
pal <- d %>% mutate(colpal = pal(value))
d
# match custom palette colpal to unique values in df var
<- colorRampPalette(colors = c(col_low, col_high))
colv <- colv(d$value %>% length)
colpal <- col_numeric(palette = colpal, domain = d$value)
pal <- d %>% mutate(colpal = pal(value))
d
# add optional highlight colours
<- d %>% mutate_at("colpal", funs(case_when(id_name == "name1" ~ "red", TRUE ~ colpal)))
d
# match colours based on df variable values
<- d %>% mutate(colpal = case_when(id_name %in% "name1" ~ "red", TRUE ~ colpal # or e.g. 'blue'
d
))ggplot() + geom_sf(data = d, aes(col = colpal)) + scale_color_manual(values = d$colpal %>% unique) # then add manual colpal from df
Loop through different colpals and save plots to dir
<- df$var1 %>% unique
vars <- c("Peach", "PinkYl", "Burg")
colv for (i in seq_along(vars)) {
<- df %>% filter(var1 == vars[i])
df <- "Month"
xlab <- "Day"
ylab <- df %>% pull(var2) %>% n_distinct()
nn <- c(sequential_hcl(nn, colv[i]) %>% .[nn], sequential_hcl(nn, colv[i]) %>% .[1]) # set col gradient
colpal ggplot() + geom_tile(data = df, aes(v1, v2, fill = ar2)) + scale_fill_gradient(low = colpal[1], high = colpal[2],
guide = "colourbar", na.value = "transparent") # create custom gradient
ggsave(here::here("plot", var1[i], "_activity.png"), device = "png")
}
Create gradient colour for area plot (AUC)
library(minisvg)
library(devout)
library(devoutsvg)
library(poissoned)
library(svgpatternsimple)
require(ggplot2)
require(ggdark)
# create gradient
<- create_pattern_gradient(id = "p1", angle = 90, colour1 = "#1A1A1A", colour2 = "#63CB99",
gradient_pattern alpha = 0.8)
$show()
gradient_pattern
# save gradient as svg
<- list(`#000001` = list(fill = gradient_pattern))
my_pattern_list
svgout(filename = "line-chart-with-gradient-shade.svg", pattern_list = my_pattern_list, width = 10, height = 5)
# plot
ggplot(btc, aes(x = Date, y = Price)) + geom_line(color = "#63CB99", size = 0.4, alpha = 0.9) + geom_area(alpha = 0.3,
fill = "#000001", color = alpha(0.1)) + ggtitle("BTC price, USD") + scale_y_continuous(labels = scales::comma)
Glow effect for line plot
require(ggshadow)
require(ggplot2)
require(ggthemes)
ggplot(btc, aes(x = Date, y = Price)) + geom_glowline(color = "gold", shadowcolour = "orange") + theme_solarized_2(light = FALSE) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
Fill plot view with image
require(png)
require(jpeg)
<- img %>% readPNG()
imgr ggplot() + annotation_raster(imgr, -Inf, Inf, -Inf, Inf)
Fill geom with patterns/images https://coolbutuseless.github.io/package/ggpattern/index.html
Read in png, recolor, write as svg, and append to df
::here("img",paste0(ifh,".png")) %>%
hereimage_read(strip = T) %>%
# image_scale(c(100,100)) %>%
image_fill("transparent") %>%
image_colorize(color = colv_hi,opacity = 70) %>% # recolor img
image_write(here::here("img",paste0(ifh,"2.png")) ,format = "png", depth=NULL)
# append to df
$img <- here::here("img",paste0(ifh,"2.png")) df
library(ggplot2)
<- 1:100
x
<- function(yy, colour = "black") {
my_geom_y list(geom_line(aes(y = yy), col = colour), data = data.frame(x, yy), geom_point(aes(y = yy), col = colour,
data = data.frame(x, yy)))
}
ggplot(aes(x)) + my_geom_y(x, "red") + my_geom_y(dlnorm(x), "blue") + my_geom_y((x^1.1), "black") + my_geom_y(x/2,
"yellow")
Highlight variables in plot
library(ggplot2)
library(gghighlight)
ggplot(mpg, aes(x = cty, y = hwy)) + geom_point(color = "red", size = 2) + gghighlight(class == "midsize")
Set inner circle width for circular barplot
<- 40
ylim ggplot() + geom_histogram(data = d, aes(xx, id, fill = yy), size = 0, position = "stack", stat = "identity",
show.legend = F) + scale_fill_manual(values = adjustcolor(colv, 1), aesthetics = c("col", "fill")) +
facet_wrap(~zz) + theme_classic() + coord_polar(start = 0.25) + scale_x_continuous(breaks = 1:12,
labels = xtick) + # option 1
scale_y_continuous(expand = c(0.2, 0)) + # option 2
scale_y_continuous(limits = c(-10, NA), breaks = seq(0, ylim, ylim/4), labels = seq(0, ylim, ylim/4))
Add histogram dist to boxplots (from Eli data)
<- d$yy %>% unique
limits <- colorspace::sequential_hcl(limits, "Blues")
colv require(ggdist)
ggplot(data = d, aes(x = xx, y = yy,
col = yy, fill = yy
+
)) geom_boxplot(outlier.color = NA) + # boxplot
geom_jitter(height = 0.2) + # jitter points
::stat_dots(binwidth = 0.2, # opt 1: dot plot
ggdistside = "left",
justification = 1.1,
col = NA) +
::stat_halfeye(slab_type = "pdf",
ggdistlimits = c(1, NA), # rm data < 1
adjust = 0.5, # opt 2: point dist
width = 0.5,
.width = 0, # decrease iqr line width
justification = -0.5, # move dist above box
point_colour = NA) +
scale_y_discrete(limits=limits) + # reorder xaxis
scale_colour_manual(values = colv,aesthetics = "col", limits = limits, labels = limits) + # keep solid col for boxplot
scale_fill_manual(values = adjustcolor(colv,0.7), aesthetics = "fill",limits = limits, labels = limits) + # add alpha to boxplot fill
theme_classic()
Maintain order of variables in df when plotting
<- df$var1 %>% pull
limits %>% ggplot() + geom_col(aes(x, y)) + scale_x_discrete(limits = limits)
df
# option 2 (works for factor variables with barplot)
require(forcats)
%>% ggplot() + geom_bar(aes(fct_infreq(y)))
df
# reverse variable order
%>% ggplot() + geom_bar(aes(fct_rev(y))) df
### opt 1 first create and save plot inset to local dir
<- ggplot() + geom_point(data = inset_data)
plot_inset #
ggsave("plot_inset.png", plot_inset)
<- "plot_inset.png" %>% readPNG() # read in saved plot
plot_inset
# main plot
ggplot() + geom_sf(data = data) + # add plot inset
annotation_raster(plot_inset, xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax) + # themes
theme_nothing()
### opt 2
ggdraw() + draw_plot(main1, 0, 0, 1, 1) + draw_plot(legend1, 0.15, 0.7, 0.18, 0.18)
Custom shape for legend
# ?draw_key # see available glyphs
require(ggplot2)
require(dplyr)
require(colorspace)
<- "pointrange"
glyph <- data.frame(xx = rep(1:5,each=3),
df yy = 1:15,
group = rep(c("A","B","C"),each=5))
ggplot(data=df,aes(xx,yy,col = group, fill = group)) +
geom_line(key_glyph = glyph) + # set shape for legend
scale_fill_discrete_sequential(name = paste0(glyph, " legend"), "Reds", aesthetics = "col") +
theme_bw() +
guides(col = guide_legend(
override.aes = list(size = 1) # set custom legend size
))
Fine tune legend features e.g. text, padding, vertical/horizontal
spacing
<- data.frame(xx = sample(100, 100), yy = rnorm(100))
df ggplot(data = df, aes(xx, yy, col = yy, fill = yy)) + geom_point() + theme_classic() + theme(legend.position = "bottom") +
# legend guide for colourbar
guides(fill = guide_colorbar(title = "Continuous", label.position = "left")) + # legend guid for categorical
guides(fill = guide_legend(title = "Categorical", label.position = "right"))
Toggle legend when using scale_*_()
functions
ggplot() + geom_point(data = df, aes(fill = var1)) + scale_fill_manual(values = colpal, aesthetics = "fill",
guide = F) # T/F to toggle show legend
Customise attributes of two separate legends e.g. size and colour bar
# set colourbar for var1 (color gradient) but also change colour/fill of legend for var2 (size)
ggplot() + geom_sf(data = df, aes(col = var1, fill = var1, size = var2)) + # var 1 attributes (colour/fill gradient)
scale_fill_gradientn(name = title1, colours = adjustcolor(colpal, 0.5), aesthetics = c("col", "fill"),
na.value = "#EFEFEF") + # var 2 attributes (size)
guides(size = guide_legend(title = title2, override.aes = list(fill = col_var2, alpha = 0.5, col = col_var2) # change colour for size legend (var2)
))
Change legend font, size, bg, opacity, and position
<- 0.5
opac theme(legend.position=c(0.2,0.2), #xy from bottom left
legend.key.size = unit(0.5, "cm"), # size
legend.background = element_rect(fill=alpha(fg, opac)), # legend background
legend.title = element_text(family = family,colour = col_font),
legend.text = element_text(family = family,colour = col_font)
)
Biscale legend
require(biscale)
<- bi_class(df, sf1, sf2, dim = 3)
data <- bi_legend(pal = "GrPink",
legend dim = 3,
xlab = "More sf1",
ylab = "More sf2",
size = 12)
<- ggplot() +
map geom_tile(data = data , aes(x = x, y = y, fill = bi_class), show.legend = F) +
bi_scale_fill(pal = "GrPink", dim = 3) + # create biscale
bi_theme()
# combine legend and map
ggdraw() +
draw_plot(map, 0, 0, 1, 1) +
draw_plot(legend, 0.15, 0.7, 0.18, 0.18)
Blank theme with full legend
require(ggthemes)
+ theme_map() + theme(legend.background = element_rect(fill = "transparent")) p1
Setting custom legend position for wrapped/stacked plots
require(patchwork)
# can specify legend position using theme(legend.position=...)
wrap_plots(p, p1, p2, ncol = 2, guides = "collect" #'keep' 'auto'
)
Combine df aes elements (e.g. colour and size) into one legend
require(dplyr)
require(ggplot2)
require(colorspace)
<- tibble(x = 1:10, y = 11:20, size = 1:10)
df <- sequential_hcl(df$size %>% n_distinct(), "Burg")
colpal ggplot() + geom_point(data = df, aes(x, y, size = size, colour = size)) + scale_colour_gradientn(colours = colpal,
aesthetics = "colour", guide = "legend")
Update legend title
ggplot() + labs(fill = "title") # opt 1
ggplot() + guides(fill = guide_legend(title = "title")) # opt 2
ggplot() + scale_fill_discrete(name = "title") # opt 3
Add brackets to axes
# install.packages('lemon')
require(lemon)
ggplot() + geom_jitter(data = mpg, aes(cyl, hwy, colour = class), width = 0.2) + coord_flex_cart(bottom = brackets_horizontal(tick.length = 0))
Extract variable name as character
require(ggplot2)
require(palmerpenguins)
<- theme_classic()
my_theme <- function(v1, v2, v3) {
plot_penguin <- ensym(v1) # turn var into character
var1 <- ensym(v2)
var2 <- ensym(v3)
var3 ggplot(penguins) + geom_point(aes({
{
var1
}
}, {
{
var2
}colour = {
},
{
var3
}+ my_theme + ggtitle(paste0(var1, " vs ", var2, " by ", var3))
}))
}plot_penguin(bill_depth_mm, bill_length_mm, species)
Remove buffer around maps to crop map to plot edges
+ scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0)) p1
Set text behind plot area/map/data
ggplot() + geom_text(data = ttl, aes(x, y, label = label), check_overlap = T) + geom_sf(data = sf) +
coord_sf(crs = prj, xlim = c(bbox[1], bbox[3]), ylim = c(bbox[2], bbox[4])) + labs(x = NULL, y = NULL) +
# themes
theme_nothing() + theme(panel.grid.major = element_line(colour = border, linetype = 3, size = 0.2), plot.background = element_rect(fill = "transparent",
colour = NA), panel.background = element_rect(fill = "transparent"), axis.text = element_blank(),
axis.ticks.length = unit(0, "null"), plot.margin = unit(c(0.1, 0.1, 0.1, 0.1), "mm"), panel.ontop = F)
Customise ggplot text with colours
require(ggtext)
<- paste0("<span style='font-family: Avenir;'>Climate risk in Vietnam <br>
ttl <span style='font-size: 30pt'> Exposure of
<span style='color:",colv1,";'>Coffee</span>,
<span style='color:",colv2,";'>Cashew</span>, and
<span style='color:",colv3,";'>Cassava</span>
</span></span>") %>% purrr::map(htmltools::HTML)
+ theme(plot.title = element_markdown(lineheight = 1)) + # add custom ggtext
p labs(title = ttl)
# vlist <- c(coff,cash,cass)
# lapply(vlist,function(x) {colnames(x) = rep(c('Index',"geometry"),times = vlist %>% length/2)})
Add curved arrows/points to text labels, unicode chars, math expressions, etc
require(ggrepel)
require(ggplot2)
set.seed(42)
ggplot(mtcars, aes(wt, mpg, label = carb)) + geom_point(color = "red") + geom_text_repel(nudge_x = 0.15,
box.padding = 0.5, nudge_y = 1, segment.curvature = -0.1, segment.ncp = 3, segment.angle = 20)
Use sf geometry coords when adding text
<- df$size
var1 ggplot() + geom_sf(data = sf) + geom_text(data = df, aes(df$geometry %>% st_coordinates %>% .[, 1], df$geometry %>%
%>% .[, 2], label = .data[[var1]])) st_coordinates
Repel labels (df and sf)
<- city_df %>% mutate_at("city", str_to_upper) %>% mutate_at("city", ~str_replace_all(.,
city_df_labels " ", "\n")) # %>%
# slice(-c(6,8,10,18,28))
# repel labels for sf and projected sf
ggplot() + geom_text_repel(data = city_df_labels, aes(label = city, geometry = geometry), stat = "sf_coordinates",
col = path_col, size = city_label_size, min.segment.length = Inf, max.overlaps = Inf)
# repel labels for df
ggplot() + geom_text_repel(data = city_df_labels, aes(lon, lat, label = city), col = path_col, size = city_label_size,
min.segment.length = Inf, max.overlaps = Inf)
Add text grob as plot area
require(patchwork)
require(gridExtra)
require(grid)
# opt 1
<- "Some text"
fh_grob + p2) + grid::textGrob(fh_grob)
(p1
# opt 2 - display df in plot window
<- data.frame(1:10)
fh_grob <- gridExtra::tableGrob(fh_grob)
pft ::grid.arrange(p1, pft) gridExtra
Save as any output
require(rstudioapi)
%>% rstudioapi::savePlotAsImage("p.png", format = "png", width, height) p
Scale size of points manually
ggplot() + geom_point(data = df, aes(x, y, size = var1)) + scale_size("size_area", range = c(-20, 20))
Contour/heatmap
= 50
bins <- 6 # match to 'levels' in plot (get from plotting first)
ll <- sequential_hcl(ll, "Reds")
lcol ggplot() + geom_density2d_filled(data = df, aes(lon, lat, fill = ..level.., col = ..level.., bins = bins)) +
scale_fill_gradientn(colors = colpal, aesthetics = c("col", "fill"))
Freescale grid layout
require(tmap)
# opt 1 - convert to spdf
<- sf %>% as("Spatial")
spp ggplot() +
geom_spatial_tile(data = spp) +
facet_wrap(~id, scales = "free")
# opt 2 - tmap
require(tmap)
%>%
sf tm_shape() +
tm_borders(group = "id") + # set plot area
tm_polygons("area",palette = "BuPu",legend.show = F) +
tm_facets(by = "id") + # facet by var
tm_layout(frame = F,
frame.lwd = NA,
panel.label.bg.color = NA,
panel.label.size = 2,
main.title = ttl,
main.title.position = "center",
main.title.size = 3,
main.title.fontface = "bold")
Mosaic/tile plot
require(ragg)
# tile, pattern and mosaic plots {ragg}
Animated plots (see commented out examples below)
Value dot plot (see commented out examples below)
Interactive map and chart plots (ggiraph)
library(tidycensus)
library(tidyverse)
library(ggiraph)
library(scales)
library(patchwork)
library(tigris)
<- get_acs(geography = "state", variables = "DP03_0024P", year = 2022, survey = "acs1", geometry = TRUE) %>%
us_wfh filter(GEOID != "11") %>% shift_geometry(position = "outside") %>% mutate(tooltip = paste(NAME, estimate,
sep = ": "))
<- ggplot(us_wfh, aes(fill = estimate)) + geom_sf_interactive(aes(tooltip = tooltip, data_id = GEOID),
gg size = 0.1) + scale_fill_viridis_c(option = "rocket", direction = -1, labels = label_percent(scale = 1)) +
labs(title = "Percent of workers who work at home", caption = "Data source: 2022 1-year ACS, US Census Bureau",
fill = "ACS estimate") + theme_void()
<- ggplot(us_wfh, aes(y = estimate, x = reorder(NAME, -estimate), fill = estimate)) + geom_col_interactive(aes(data_id = GEOID)) +
gg_bar scale_fill_viridis_c(guide = "none", option = "rocket", direction = -1) + scale_y_continuous(labels = scales::label_percent(scale = 1)) +
theme_minimal(base_size = 8) + labs(x = "", y = "") + theme(axis.text.x = element_text(angle = 45,
vjust = 1, hjust = 1), legend.position = "bottom", legend.direction = "horizontal")
girafe(ggobj = wrap_plots(gg, gg_bar, widths = c(8, 8), heights = c(6, 2), ncol = 1), options = list(opts_hover(css = ""),
opts_hover_inv(css = "opacity:0.25;")))
Word clouds
::install_github("lchiffon/wordcloud2") # need to use dev ver
devtools<- here::here("face.png") # needs to be black and white
figpath <- data.frame(keyword = LETTERS[1:20], freq = sample(100, 20))
wcld
# run twice if first time doesn't run
wordcloud2(wcld, figPath = figpath, color = c("skyblue", "red"), backgroundColor = "pink")
# other options https://spencerschien.info/post/data_viz_how_to/dense_word_clouds/
# https://lepennec.github.io/ggwordcloud/
# https://stackoverflow.com/questions/42028462/wordcloud-with-a-specific-shape