Saskia A. Otto
Postdoctoral Researcher
Explore spatial patterns of summer sea surface temperature in the Baltic Sea graphically:
ggplot(data, mapping = aes())
where you supply a dataset and (default) aesthetic mappinggeom_function
xlim()
facet_wrap()
coord_flip()
theme_bw()
ggsave()
source of image (topright): older version of Data Visualization with ggplot cheat sheet (licensed under CC-BY-SA)
p <- ggplot(hydro, aes(long, lat))
str(p)
ggplot(data, aes(x, y, color, size, shape, linetype, fill, alpha, label, family, width, hjust, vjust, ...))
aes()
to associate the name of the aesthetic with a variable to display, for single values aes()
not neededAssign single value for aesthethic colour (aes()
not needed):
ggplot(hydro_april, aes(long, lat)) +
geom_point(colour = "red")
Assign single value for aesthethic colour (aes()
not needed):
ggplot(hydro_april, aes(long, lat)) +
geom_point(colour = "red")
Map colour to variable "day" with automatic colour setting:
ggplot(hydro_april, aes(long, lat)) +
geom_point(aes(colour = factor(day)))
Colour is the most popular aesthetic after position. It is also the easiest to misuse.
It can be specified with
colours()
. Colour is the most popular aesthetic after position. It is also the easiest to misuse.
It can be specified with
colours()
. col_df <- data.frame(x = 1:4, y = 1:4)
ggplot(col_df, aes(x, y)) +
geom_point(colour = c("blue4",
"grey60", "#556B2F", "#8B7355"),
size = 7)
For some geoms/point shapes you can specify 2 colour aesthetics: the border colour (=colour) and the inside (=fill)
ggplot(hydro, aes(x = fmonth)) +
geom_bar(aes(colour = fmonth), fill = "white")
To make colours transparent use alpha aesthethics
col_df <- data.frame(x = 1:5, y = 1:5)
ggplot(col_df, aes(x, y)) +
geom_point(fill = "red",
alpha = c(.1,.3,.5,.7,1.0),
size = 5, shape = 21)
Default shape is 19
shapes <- data.frame(
shape = c(0:19, 22, 21, 24, 23, 20),
x = 0:24 %/% 5, y = -(0:24 %% 5))
ggplot(shapes, aes(x, y)) +
geom_point(aes(shape = shape),
size = 10, fill = "red") +
geom_text(aes(label = shape),
hjust = 0, nudge_x = 0.15) +
scale_shape_identity() +
expand_limits(x = 4.1) +
scale_x_continuous(NULL,breaks=NULL) +
scale_y_continuous(NULL,breaks=NULL)
Line types can be specified with an integer or name: 0 = blank, 1 = solid, 2 = dashed, 3 = dotted, 4 = dotdash, 5 = longdash, 6 = twodash, as shown below:
lty <- c("blank", "solid", "dashed",
"dotted", "dotdash",
"longdash","twodash")
linetypes <- data.frame(
y = seq_along(lty), lty = lty)
ggplot(linetypes, aes(0, y)) +
geom_segment(aes(xend = 5,
yend = y, linetype = lty)) +
scale_linetype_identity() +
geom_text(aes(label = lty),
hjust = 0, nudge_y = 0.2) +
scale_x_continuous(NULL,breaks=NULL) +
scale_y_continuous(NULL,breaks=NULL)
There are only three fonts that are guaranteed to work everywhere: "sans" (the default), "serif", or "mono":
df <- data.frame(x = 1, y = 3:1,
family = c("sans", "serif", "mono"))
ggplot(df, aes(x, y)) +
geom_text(aes(label = family,
family = family), size = 15)
Horizontal and vertical justification have the same parameterisation, either a string (“top”, “middle”, “bottom”, “left”, “center”, “right”) or a number between 0 and 1:
just <- expand.grid(hjust = c(0,0.5,1),
vjust = c(0, 0.5, 1))
just$label <- paste0(just$hjust, ", ",
just$vjust)
ggplot(just, aes(hjust, vjust)) +
geom_point(colour = "grey70",
size = 5) +
geom_text(aes(label = label,
hjust = hjust, vjust = vjust),
size = 7)
?geom_point
)aes(colour = psal < 10)
?ggplot(data = hydro) +
geom_point(mapping = aes(x = psal, y = temp, color = "blue"))
aes()
for a specific aesthetic):
scale_aesthetic ...
scale_x_log10()
- Plot x on log10 scalescale_x_reverse()
- Reverse axis direction scale_x_sqrt()
- Plot x on square root scaleggplot2's default discrete palettes (depends on how many colors are needed)
sst_sum <- hydro %>% filter(pres == 1, fmonth %in% 5:8)
sst_sum$fmonth <- factor(sst_sum$fmonth) # to remove other factor levels
p <- ggplot(sst_sum, aes(x = long, y = lat, colour = fmonth)) + geom_point()
scale_colour_manual()
p
p + scale_colour_manual(values =
c("red","blue","grey30","green3"))
scale_colour_hue()
scale_colour_hue is the default colour scale → does not generate colour-blind safe palettes
p + scale_colour_hue()
p + scale_colour_hue(l = 50, c = 150,
h = c(150, 270) )
scale_colour_grey()
p + scale_colour_grey()
scale_colour_brewer()
p + scale_colour_brewer()
The brewer scales provides nice colour schemes from the ColorBrewer particularly tailored for maps: http://colorbrewer2.org
To see a list of each brewer palette, run the following command
library(RColorBrewer)
display.brewer.all()
# Same dataset as before
sst_sum <- hydro %>% filter(pres == 1, fmonth %in% 5:8)
sst_sum$fmonth <- factor(sst_sum$fmonth)
p <- ggplot(sst_sum, aes(x = long, y = lat, colour = temp)) + geom_point()
scale_colour_gradient()
scale_colour_gradient is the default colour scale. Creates a two colour gradient (low-high):
p
p + scale_colour_gradient()
scale_colour_gradient()
Change a few settings ...
p + scale_colour_gradient(
low = "yellow", high = "red")
p + scale_colour_gradient(
low = "white", high = "maroon4",
na.value = "yellow")
scale_colour_gradient2()
Creates a diverging colour gradient (low-mid-high):
p + scale_colour_gradient2(midpoint=10)
Set the midpoint from 0 to 10.
p + scale_colour_gradient2(midpoint=15,
low = "blue", mid = "yellow",
high = "red", na.value = "black")
p <- ggplot(sst_sum, aes(long,lat)) +
geom_point(aes(shape = fmonth))
p + scale_shape_manual(values = 0:3)
p <- ggplot(sst_sum, aes(long,lat)) +
geom_point(aes(shape = fmonth))
p + scale_shape_manual(values = 0:3)
When your data variable already contains values that could be used as aesthetic values ggplot2 handles them directly without producing a legend (the variable is considered as scaled).
Use scale_shape_identity()
for continuous data:
ggplot(hydro_april, aes(long, lat)) +
geom_point(aes(shape = day)) +
scale_shape_identity()
sst_june <- hydro %>% filter(pres == 1, fmonth == "6")
You can use scale_size()
, scale_size_area()
, or scale_radius()
:
p <- ggplot(sst_june, aes(long,lat))+
geom_point(aes(size = temp),
colour = "orange2", alpha=0.3)
p + scale_radius(range=c(1,10),
breaks=seq(5,20,2.5), limits=c(4,20))
There are scales for every aesthetic ggplot2 uses. To see a complete list with examples, visit http://docs.ggplot2.org/current
Screenshot from webpage (taken Dec. 2017)
Look at display.brewer.all()
in the RColorbrewer package. Experiment with the different palettes available for the brewer scale. Add a color scheme that you like for temp in the sst_sum
data.
Facets divide a plot into subplots based on the values of one or more discrete variables
To adjust facet labels set labeller
p + facet_grid(pres ~ fmonth, labeller = label_both)
facet_grid()
you should usually put the variable with more unique levels in the columns. Why??facet_wrap
. What does nrow do? What does ncol do? What other options control the layout of the individual panels? Why doesn’t facet_grid()
have nrow and ncol argument?5.What plots are generated by the following code? What does .
do?
temp_sum <- hydro %>% filter(pres %in% c(1, 50), fmonth %in% 5:8)
ggplot(data = temp_sum) +
geom_point(mapping = aes(x = long, y = lat)) +
facet_grid(fmonth ~ .)
ggplot(data = temp_sum) +
geom_point(mapping = aes(x = long, y = lat)) +
facet_grid(. ~ pres)
Which months are most frequently sampled?
In the grammar of graphics, a pie chart is a stacked bar graph in polar coordinates.
monthly_pie <- hydro %>%
select(fmonth, station, cruise,
date_time) %>% distinct() %>%
group_by(fmonth) %>%
mutate(year = "y")
ggplot(monthly_pie, aes(year)) +
geom_bar(aes(fill = fmonth)) +
scale_fill_brewer(
palette="Paired") +
coord_polar(theta="y", direction=-1)
What is now needed is some element cleaning...
coord_map()
projects a portion of the earth, which is approximately spherical, onto a flat 2D plane using any projection defined by the mapproj package.
# Showing the world map:
world <- map_data("world")
worldmap <- ggplot(world, aes(
x=long, y=lat, group=group)) +
geom_polygon(fill = "white",
colour = "black")
worldmap + coord_map("ortho",
orientation = c(55, 20, 0))
Simply add the axis limits to coord_map()
worldmap + coord_map("ortho",
orientation = c(55, 20, 0),
xlim = c(10, 30), ylim = c(54,66))
coord_map()
and coord_quickmap()
?
The title and subtitle should provide main findings.
There are different functions available to change labels:
xlab()
: change the label of the x-axisylab()
: change the label of the y-axisggtitle()
: provide a title (and subtitle)labs()
: change all labelsp <- ggplot(sst_june, aes(long,lat)) +
geom_point(aes(colour = temp)) +
scale_colour_gradient(
low = "white", high = "red")
# Labels added here
p + xlab("Longitude") +
ylab("Latitude") +
ggtitle(label = "Thermal patterns
in the Baltic Sea",
subtitle = "Sea surface temperature
(1m depth) in June 2015")
guides()
guide_legend()
or guide_colourbar()
, which can be specified in each scale_* function or in guides()
:p <- ggplot(sst_sum, aes(long,lat)) +
geom_point(aes(colour = temp,
shape = fmonth)) +
scale_colour_gradient(
low = "white", high = "red")
p2 <- p + guides(colour =
guide_colourbar(order = 1,
title = "SST (in °C)"),
shape = guide_legend(
order = 2,
title = "Summer months",
title.position = "bottom",
nrow = 2, byrow = TRUE,
title.theme = element_text(
colour = "red", angle = 0)))
You can change the labels (and more) in the scale_*_functions:
p3 <- p2 + scale_shape_discrete(
labels=c("May","June","July","Aug"))
p3
theme()
or even create your own theme.Change the legend position with theme()
p3 + theme(legend.position = "bottom",
legend.justification = "left")
p3 + theme(
legend.position = c(0.01, .95),
legend.justification = c("left", "top"),
legend.box.just = "left"
)
See for more info
?theme
and p3 + theme_bw()
p3 + theme_gray()
p3 + theme_classic()
p3 + theme_light()
p3 + theme_linedraw()
p3 + theme_minimal()
p3 + theme_void()
labs()
do? Read the documentation.par()
and layout()
do not workpar()
and layout()
do not workhydro
dataset:
Demo plots, each assigned to an object
a <- hydro %>%
select(fmonth, station, cruise, date_time) %>%
distinct() %>% group_by(fmonth) %>%
ggplot(aes(x = fmonth)) +
geom_bar(aes(fill = fmonth)) +
guides(fill = "none") +
scale_fill_brewer(palette = "Paired")
b <- ggplot(hydro, aes(x = psal, y = temp, col = day)) +
geom_point()
c <- hydro %>%
filter(pres %in% c(1, 50), fmonth %in% 5:8) %>%
ggplot(aes(long,lat))+
geom_point(aes(colour = temp)) +
scale_colour_gradient(low = "white", high = "red") +
facet_grid(. ~ fmonth)
viewport()
To have a small subplot embedded drawn on top of the main plot
print()
functionThe viewport()
function, has as arguments x
, y
, width
and height
to control the position and size of the viewport.
library(grid)
# specify the viewport for the subplot
subvp <- viewport(x = 0.7, y = 0.8,
width = 0.3, height = 0.3)
b
print(a, vp = subvp)
grid.arrange()
grid.arrange()
set up a so-called gtable layout to place multiple grobs on a page in the current device.library(gridExtra)
grid.arrange(a, b, c,
nrow = 2, ncol = 2)
grid.arrange()
with arrangeGrob()
arrangeGrob()
when listing the plotting objects. This function takes also the row or column number as input:grid.arrange(
arrangeGrob(a, b, ncol = 2),
# a and b will be in the 1st row,
# splitted into 2 columns
c, # c will be in the 2nd row
nrow = 2
)
grid.arrange()
with argument layout_matrix
layout_matrix
argument for changing the row or column span of a plot (more flexible than arrangeGrob()
):grid.arrange(a, b, c,
nrow = 2, ncol = 2,
layout_matrix = matrix(
c(1,2,2,3,3,3),
nrow = 2, byrow = TRUE))
6 grid cells are specified in the matrix
theme_classic()
), different font sizesplot_grid()
is a shortcut function with limited adjustmentslibrary(cowplot)
plot_grid(a,b,c, labels = c("a)", "b)", "c)"), ncol = 3)
For more adjustments (location and size) use in combination:
ggdraw()
→ initializes an empty drawing canvasdraw_plot()
→ places a single plot onto the canvasdraw_plot_label()
→ adds labels to the plots (default is upper left corner)abc <- ggdraw() +
draw_plot(a, x = 0, y = .5, width = .5, height = .5) +
draw_plot(b, x = .5, y = .5, width = .5, height = .5) +
draw_plot(c, x = 0, y = 0, width = 1, height = .5) +
draw_plot_label(label = c("a)", "b)", "c)"),
x = c(0, 0.5, 0), y = c(1, 1, 0.5), size = 15)
abc
ggsave()
(in ggplot2) can be used to save ggplots as
pdf.save_plot()
(in cowplot) → grid layout can be specified so that the output pdf is nicely formatted and scaledsave_plot("abc3.pdf", abc,
base_aspect_ratio = 1.3, # this makes room for a figure legend
# the grid specification adjusts the scales:
ncol = 2, nrow = 2 )
Explore spatial patterns of summer sea surface temperature in the Baltic Sea graphically:
If you don't know how, follow these steps
Try to reproduce some of the plots in this presentation and the quiz and read chapter 3 on data visualization in 'R for Data Science' or the book ggplot2: Elegant Graphics for Data Analysis by H. Wickham.
Then figure out how to do an interpolation plot of the thermal regime along the latitude/longitude gradient.
Then go grab a coffee, lean back and enjoy the rest of the day...!
For more information contact me: saskia.otto@uni-hamburg.de
http://www.researchgate.net/profile/Saskia_Otto
http://www.github.com/saskiaotto
This work is licensed under a
Creative Commons Attribution-ShareAlike 4.0 International License except for the
borrowed and mentioned with proper source: statements.
Image on title and end slide: Section of an infrared satallite image showing the Larsen C
ice shelf on the Antarctic
Peninsula - USGS/NASA Landsat:
A Crack of Light in the Polar Dark, Landsat 8 - TIRS, June 17, 2017
(under CC0 license)
world <- map_data("world")
worldmap <- ggplot(world, aes(x = long, y = lat)) +
geom_polygon(aes(group = group), fill = "ivory3", colour = "black")
baltic <- worldmap + coord_map("ortho", xlim = c(10, 30), ylim = c(54,66))
baltic + geom_point(data = sst_sum, aes(x = long, y = lat, colour = temp), size = 1) +
scale_colour_gradient(low = "white", high = "red") +
guides(colour = guide_colourbar(title = "SST (in °C)")) +
facet_wrap(~fmonth, labeller = label_both) +
ggtitle(label = "Thermal pattern in the Baltic Sea",
subtitle = "SST in the summer months of 2015") +
xlab("Longitude") + ylab("Latitude") +
ggthemes::theme_base() +
theme(legend.position = "bottom", legend.title.align = 1,
legend.title = element_text(colour = "red", angle = 0),
panel.background = element_rect(fill = "lightblue1")
)