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_functionxlim()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 labels
p <- 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 work
par() 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_matrixlayout_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")
)