forked from hadley/ggplot2-book
-
Notifications
You must be signed in to change notification settings - Fork 0
/
position.rmd
534 lines (401 loc) · 24.9 KB
/
position.rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
---
title: position
output: oldbookdown::html_chapter
---
```{r position, include = FALSE}
chapter <- "position"
source("common.R")
```
# Positioning {#cha:position}
## Introduction
This chapter discusses position, particularly how facets are laid out on a page, and how coordinate systems within a panel work. There are four components that control position. You have already learned about two of them that work within a facet: \index{Positioning}
* __Position adjustments__ adjust the position of overlapping objects
within a layer. These are most useful for bar and other interval geoms, but
can be useful in other situations ([link to section](#sec:position)).
* __Position scales__ control how the values in the data are mapped to
positions on the plot ([link to section](#sub:scale-position)).
This chapter will describe the other two components and show you how all four pieces fit together:
* __Facetting__ is a mechanism for automatically laying out multiple plots
on a page. It splits the data into subsets, and then plots each subset
in a different panel. Such plots are often called small multiples or trellis graphics
([link to section](#sec:facetting)).
* __Coordinate systems__ control how the two independent position scales
are combined to create a 2d coordinate system. The most common
coordinate system is Cartesian, but other coordinate systems can be useful
in special circumstances ([link to section](#sec:coord)).
## Facetting {#sec:facetting}
You first encountered facetting in [getting started](#sec:qplot-facetting). Facetting generates small multiples each showing a different subset of the data. Small multiples are a powerful tool for exploratory data analysis: you can rapidly compare patterns in different parts of the data and see whether they are the same or different. This section will discuss how you can fine-tune facets, particularly the way in which they interact with position scales. \index{Facetting} \index{Positioning!facetting}
There are three types of facetting:
* `facet_null()`: a single plot, the default. \indexf{facet\_null}
* `facet_wrap()`: "wraps" a 1d ribbon of panels into 2d.
* `facet_grid()`: produces a 2d grid of panels defined by variables which
form the rows and columns.
The differences between `facet_wrap()` and `facet_grid()` are illustrated in Figure \ref{fig:facet-sketch}.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.75\linewidth]{diagrams/position-facets}
\caption{A sketch illustrating the difference between the two facetting systems. \texttt{facet\_grid()} (left) is fundamentally 2d, being made up of two independent components. \texttt{facet\_wrap()} (right) is 1d, but wrapped into 2d to save space.}
\label{fig:facet-sketch}
\end{figure}
Faceted plots have the capability to fill up a lot of space, so for this chapter we will use a subset of the mpg dataset that has a manageable number of levels: three cylinders (4, 6, 8), two types of drive train (4 and f), and six classes.
```{r mpg2}
mpg2 <- subset(mpg, cyl != 5 & drv %in% c("4", "f") & class != "2seater")
```
### Facet wrap {#sub:facet-wrap}
`facet_wrap()` makes a long ribbon of panels (generated by any number of variables) and wraps it into 2d. This is useful if you have a single variable with many levels and want to arrange the plots in a more space efficient manner. \index{Facetting!wrapped} \indexf{facet\_wrap} \indexc{\textasciitilde}
You can control how the ribbon is wrapped into a grid with `ncol`, `nrow`, `as.table` and `dir`. `ncol` and `nrow` control how many columns and rows (you only need to set one). `as.table` controls whether the facets are laid out like a table (`TRUE`), with highest values at the bottom-right, or a plot (`FALSE`), with the highest values at the top-right. `dir` controls the direction of wrap: **h**orizontal or **v**ertical.
`r columns(2, 2/3)`
```{r}
base <- ggplot(mpg2, aes(displ, hwy)) +
geom_blank() +
xlab(NULL) +
ylab(NULL)
base + facet_wrap(~class, ncol = 3)
base + facet_wrap(~class, ncol = 3, as.table = FALSE)
```
```{r}
base + facet_wrap(~class, nrow = 3)
base + facet_wrap(~class, nrow = 3, dir = "v")
```
### Facet grid
`facet_grid()` lays out plots in a 2d grid, as defined by a formula: \index{Facetting!grid} \indexf{facet\_grid}
* `. ~ a` spreads the values of `a` across the columns. This direction
facilitates comparisons of y position, because the vertical scales are
aligned.
`r columns(1, 1 / 3, 0.75)`
```{r grid-v}
base + facet_grid(. ~ cyl)
```
* `b ~ .` spreads the values of `b` down the rows. This direction
facilitates comparison of x position because the horizontal scales are
aligned. This makes it particularly useful for comparing distributions.
`r columns(1, 3 / 2, 0.30)`
```{r mpg2-h}
base + facet_grid(drv ~ .)
```
* `a ~ b` spreads `a` across columns and `b` down rows. You'll usually
want to put the variable with the greatest number of levels in the columns,
to take advantage of the aspect ratio of your screen.
`r columns(1, 2 / 3, 0.75)`
```{r grid-vh}
base + facet_grid(drv ~ cyl)
```
You can use multiple variables in the rows or columns, by "adding" them together, e.g. `a + b ~ c + d`. Variables appearing together on the rows or columns are nested in the sense that only combinations that appear in the data will appear in the plot. Variables that are specified on rows and columns will be crossed: all combinations will be shown, including those that didn't appear in the original dataset: this may result in empty panels.
### Controlling scales {#sub:controlling-scales}
For both `facet_wrap()` and `facet_grid()` you can control whether the position scales are the same in all panels (fixed) or allowed to vary between panels (free) with the `scales` parameter: \index{Facetting!interaction with scales} \index{Scales!interaction with facetting} \index{Facetting!controlling scales}
* `scales = "fixed"`: x and y scales are fixed across all panels.
* `scales = "free_x"`: the x scale is free, and the y scale is fixed.
* `scales = "free_y"`: the y scale is free, and the x scale is fixed.
* `scales = "free"`: x and y scales vary across panels.
`facet_grid()` imposes an additional constraint on the scales: all panels in a column must have the same x scale, and all panels in a row must have the same y scale. This is because each column shares an x axis, and each row shares a y axis.
Fixed scales make it easier to see patterns across panels; free scales make it easier to see patterns within panels.
`r columns(1, 1 / 2.5, 0.75)`
```{r fixed-vs-free}
p <- ggplot(mpg2, aes(cty, hwy)) +
geom_abline() +
geom_jitter(width = 0.1, height = 0.1)
p + facet_wrap(~cyl)
p + facet_wrap(~cyl, scales = "free")
```
Free scales are also useful when we want to display multiple time series that were measured on different scales. To do this, we first need to change from 'wide' to 'long' data, stacking the separate variables into a single column. An example of this is shown below with the long form of the `economics` data, and the topic is discussed in more detail in [converting data from wide to long](#sec:spread-gather). \index{Data!economics\_long@\texttt{economics\_long}}
`r columns(1, 1.2 / 1, 0.75)`
```{r time}
economics_long
ggplot(economics_long, aes(date, value)) +
geom_line() +
facet_wrap(~variable, scales = "free_y", ncol = 1)
```
`facet_grid()` has an additional parameter called `space`, which takes the same values as `scales`. When space is "free", each column (or row) will have width (or height) proportional to the range of the scale for that column (or row). This makes the scaling equal across the whole plot: 1 cm on each panel maps to the same range of data. (This is somewhat analogous to the 'sliced' axis limits of lattice.) For example, if panel a had range 2 and panel b had range 4, one-third of the space would be given to a, and two-thirds to b. This is most useful for categorical scales, where we can assign space proportionally based on the number of levels in each facet, as illustrated below.
```{r discrete-free}
mpg2$model <- reorder(mpg2$model, mpg2$cty)
mpg2$manufacturer <- reorder(mpg2$manufacturer, -mpg2$cty)
ggplot(mpg2, aes(cty, model)) +
geom_point() +
facet_grid(manufacturer ~ ., scales = "free", space = "free") +
theme(strip.text.y = element_text(angle = 0))
```
### Missing facetting variables {#sub:missing-facetting-columns}
If you are using facetting on a plot with multiple datasets, what happens when one of those datasets is missing the facetting variables? This situation commonly arises when you are adding contextual information that should be the same in all panels. For example, imagine you have a spatial display of disease faceted by gender. What happens when you add a map layer that does not contain the gender variable? Here ggplot will do what you expect: it will display the map in every facet: missing facetting variables are treated like they have all values. \index{Facetting!missing data}
Here's a simple example. Note how the single red point from `df2` appears in both panels.
`r columns(1, 1 / 2, 0.75)`
```{r}
df1 <- data.frame(x = 1:3, y = 1:3, gender = c("f", "f", "m"))
df2 <- data.frame(x = 2, y = 2)
ggplot(df1, aes(x, y)) +
geom_point(data = df2, colour = "red", size = 2) +
geom_point() +
facet_wrap(~gender)
```
This technique is particularly useful when you add annotations to make it easier to compare between facets, as shown in the next section.
### Grouping vs. facetting {#sub:group-vs-facet}
Facetting is an alternative to using aesthetics (like colour, shape or size) to differentiate groups. Both techniques have strengths and weaknesses, based around the relative positions of the subsets. \index{Facetting!vs. grouping} \index{Grouping!vs. facetting} With facetting, each group is quite far apart in its own panel, and there is no overlap between the groups. This is good if the groups overlap a lot, but it does make small differences harder to see. When using aesthetics to differentiate groups, the groups are close together and may overlap, but small differences are easier to see.
`r columns(1, 2/3)`
```{r}
df <- data.frame(
x = rnorm(120, c(0, 2, 4)),
y = rnorm(120, c(1, 2, 1)),
z = letters[1:3]
)
ggplot(df, aes(x, y)) +
geom_point(aes(colour = z))
```
`r columns(1, 1 / 3, 1)`
```{r}
ggplot(df, aes(x, y)) +
geom_point() +
facet_wrap(~z)
```
Comparisons between facets often benefit from some thoughtful annotation. For example, in this case we could show the mean of each group in every panel. You'll learn how to write summary code like this in [dplyr](#cha:dplyr). Note that we need two "z" variables: one for the facets and one for the colours. \index{Facetting!adding annotations}
```{r}
df_sum <- df %>%
group_by(z) %>%
summarise(x = mean(x), y = mean(y)) %>%
rename(z2 = z)
ggplot(df, aes(x, y)) +
geom_point() +
geom_point(data = df_sum, aes(colour = z2), size = 4) +
facet_wrap(~z)
```
Another useful technique is to put all the data in the background of each panel:
```{r}
df2 <- dplyr::select(df, -z)
ggplot(df, aes(x, y)) +
geom_point(data = df2, colour = "grey70") +
geom_point(aes(colour = z)) +
facet_wrap(~z)
```
### Continuous variables {#sub:continuous-variables}
To facet continuous variables, you must first discretise them. ggplot2 provides three helper functions to do so: \index{Facetting!by continuous variables}
* Divide the data into `n` bins each of the same length: `cut_interval(x, n)`
\indexf{cut\_interval}
* Divide the data into bins of width `width`: `cut_width(x, width)`.
\indexf{cut\_width}
* Divide the data into n bins each containing (approximately) the same
number of points: `cut_number(x, n = 10)`. \indexf{cut\_number}
They are illustrated below:
`r columns(1, 1/4, 1)`
```{r discretising}
# Bins of width 1
mpg2$disp_w <- cut_width(mpg2$displ, 1)
# Six bins of equal length
mpg2$disp_i <- cut_interval(mpg2$displ, 6)
# Six bins containing equal numbers of points
mpg2$disp_n <- cut_number(mpg2$displ, 6)
plot <- ggplot(mpg2, aes(cty, hwy)) +
geom_point() +
labs(x = NULL, y = NULL)
plot + facet_wrap(~disp_w, nrow = 1)
plot + facet_wrap(~disp_i, nrow = 1)
plot + facet_wrap(~disp_n, nrow = 1)
```
Note that the facetting formula does not evaluate functions, so you must first create a new variable containing the discretised data.
### Exercises
1. Diamonds: display the distribution of price conditional
on cut and carat. Try facetting by cut and grouping by carat. Try
facetting by carat and grouping by cut. Which do you prefer?
1. Diamonds: compare the relationship between price and carat for
each colour. What makes it hard to compare the groups? Is grouping better
or facetting? If you use facetting, what annotation might you add to
make it easier to see the differences between panels?
1. Why is `facet_wrap()` generally more useful than `facet_grid()`?
1. Recreate the following plot. It facets `mpg2` by class, overlaying
a smooth curve fit to the full dataset.
`r columns(1, 2/3, 0.75)`
```{r, echo = FALSE}
ggplot(mpg2, aes(displ, hwy)) +
geom_smooth(data = select(mpg2, -class), se = FALSE) +
geom_point() +
facet_wrap(~class, nrow = 2)
```
## Coordinate systems {#sec:coord}
Coordinate systems have two main jobs: \index{Coordinate systems}
* Combine the two position aesthetics to produce a 2d position on the plot.
The position aesthetics are called `x` and `y`, but they might be better
called position 1 and 2 because their meaning depends on the coordinate
system used. For example, with the polar coordinate system they become angle
and radius (or radius and angle), and with maps they become latitude and
longitude.
* In coordination with the faceter, coordinate systems draw axes and panel
backgrounds. While the scales control the values that appear on the axes, and
how they map from data to position, it is the coordinate system which
actually draws them. This is because their appearance depends on the
coordinate system: an angle axis looks quite different than an x axis.
There are two types of coordinate system. Linear coordinate systems preserve the shape of geoms:
* `coord_cartesian()`: the default Cartesian coordinate system,
where the 2d position of an element is given by the combination of the
x and y positions.
* `coord_flip()`: Cartesian coordinate system with x and y axes flipped.
* `coord_fixed()`: Cartesian coordinate system with a fixed aspect ratio.
On the other hand, non-linear coordinate systems can change the shapes: a straight line may no longer be straight. The closest distance between two points may no longer be a straight line.
* `coord_map()`/`coord_quickmap()`: Map projections.
* `coord_polar()`: Polar coordinates.
* `coord_trans()`: Apply arbitrary transformations to x and y positions,
after the data has been processed by the stat.
Each coordinate system is described in more detail below.
## Linear coordinate systems {#sub:cartesian}
There are three linear coordinate systems: `coord_cartesian()`, `coord_flip()`, `coord_fixed()`. \index{Coordinate systems!Cartesian} \indexf{coord\_cartesian}
### Zooming into a plot with `coord_cartesian()`
`coord_cartesian()` has arguments `xlim` and `ylim`. If you think back to the scales chapter, you might wonder why we need these. Doesn't the limits argument of the scales already allow us to control what appears on the plot? The key difference is how the limits work: when setting scale limits, any data outside the limits is thrown away; but when setting coordinate system limits we still use all the data, but we only display a small region of the plot. Setting coordinate system limits is like looking at the plot under a magnifying glass. \index{Zooming}
`r columns(3, 1)`
```{r limits-smooth}
base <- ggplot(mpg, aes(displ, hwy)) +
geom_point() +
geom_smooth()
# Full dataset
base
# Scaling to 5--7 throws away data outside that range
base + scale_x_continuous(limits = c(5, 7))
# Zooming to 5--7 keeps all the data but only shows some of it
base + coord_cartesian(xlim = c(5, 7))
```
### Flipping the axes with `coord_flip()`
\label{sub:coord-flip}
Most statistics and geoms assume you are interested in y values conditional on x values (e.g., smooth, summary, boxplot, line): in most statistical models, the x values are assumed to be measured without error. If you are interested in x conditional on y (or you just want to rotate the plot 90 degrees), you can use `coord_flip()` to exchange the x and y axes. Compare this with just exchanging the variables mapped to x and y: \index{Rotating} \index{Coordinate systems!flipped} \indexf{coord\_flip}
```{r coord-flip}
ggplot(mpg, aes(displ, cty)) +
geom_point() +
geom_smooth()
# Exchanging cty and displ rotates the plot 90 degrees, but the smooth
# is fit to the rotated data.
ggplot(mpg, aes(cty, displ)) +
geom_point() +
geom_smooth()
# coord_flip() fits the smooth to the original data, and then rotates
# the output
ggplot(mpg, aes(displ, cty)) +
geom_point() +
geom_smooth() +
coord_flip()
```
### Equal scales with `coord_fixed()`
`coord_fixed()` fixes the ratio of length on the x and y axes. The default `ratio` ensures that the x and y axes have equal scales: i.e., 1 cm along the x axis represents the same range of data as 1 cm along the y axis. The aspect ratio will also be set to ensure that the mapping is maintained regardless of the shape of the output device. See the documentation of `coord_fixed()` for more details. \index{Aspect ratio} \index{Coordinate systems!equal} \indexf{coord\_equal}
## Non-linear coordinate systems {#sub:coord-non-linear}
Unlike linear coordinates, non-linear coordinates can change the shape of geoms. For example, in polar coordinates a rectangle becomes an arc; in a map projection, the shortest path between two points is not necessarily a straight line. The code below shows how a line and a rectangle are rendered in a few different coordinate systems. \index{Transformation!coordinate system} \index{Coordinate systems!non-linear}
`r columns(3, 1)`
```{r coord-trans-ex}
rect <- data.frame(x = 50, y = 50)
line <- data.frame(x = c(1, 200), y = c(100, 1))
base <- ggplot(mapping = aes(x, y)) +
geom_tile(data = rect, aes(width = 50, height = 50)) +
geom_line(data = line) +
xlab(NULL) + ylab(NULL)
base
base + coord_polar("x")
base + coord_polar("y")
```
```{r coord-trans-ex-2}
base + coord_flip()
base + coord_trans(y = "log10")
base + coord_fixed()
```
The transformation takes part in two steps. Firstly, the parameterisation of each geom is changed to be purely location-based, rather than location- and dimension-based. For example, a bar can be represented as an x position (a location), a height and a width (two dimensions). Interpreting height and width in a non-Cartesian coordinate system is hard because a rectangle may no longer have constant height and width, so we convert to a purely location-based representation, a polygon defined by the four corners. This effectively converts all geoms to a combination of points, lines and polygons. \index{Geoms!parameterisation} \index{Coordinate systems!transformation}
Once all geoms have a location-based representation, the next step is to transform each location into the new coordinate system. It is easy to transform points, because a point is still a point no matter what coordinate system you are in. Lines and polygons are harder, because a straight line may no longer be straight in the new coordinate system. To make the problem tractable we assume that all coordinate transformations are smooth, in the sense that all very short lines will still be very short straight lines in the new coordinate system. With this assumption in hand, we can transform lines and polygons by breaking them up into many small line segments and transforming each segment. This process is called munching and is illustrated below: \index{Munching}
1. We start with a line parameterised by its two endpoints:
`r columns(1, 1, 0.40)`
```{r}
df <- data.frame(r = c(0, 1), theta = c(0, 3 / 2 * pi))
ggplot(df, aes(r, theta)) +
geom_line() +
geom_point(size = 2, colour = "red")
```
1. We break it into multiple line segments, each with two endpoints.
```{r}
interp <- function(rng, n) {
seq(rng[1], rng[2], length = n)
}
munched <- data.frame(
r = interp(df$r, 15),
theta = interp(df$theta, 15)
)
ggplot(munched, aes(r, theta)) +
geom_line() +
geom_point(size = 2, colour = "red")
```
1. We transform the locations of each piece:
`r columns(1, 2.2 / 3, 0.40)`
```{r}
transformed <- transform(munched,
x = r * sin(theta),
y = r * cos(theta)
)
ggplot(transformed, aes(x, y)) +
geom_path() +
geom_point(size = 2, colour = "red") +
coord_fixed()
```
Internally ggplot2 uses many more segments so that the result looks smooth.
### Transformations with `coord_trans()`
Like limits, we can also transform the data in two places: at the scale level or at the coordinate system level. `coord_trans()` has arguments `x` and `y` which should be strings naming the transformer or transformer objects (see [continous position scales](#sub:scale-position)). Transforming at the scale level occurs before statistics are computed and does not change the shape of the geom. Transforming at the coordinate system level occurs after the statistics have been computed, and does affect the shape of the geom. Using both together allows us to model the data on a transformed scale and then backtransform it for interpretation: a common pattern in analysis. \index{Transformation!coordinate system} \index{Coordinate systems!transformed} \indexf{coord\_trans}
`r columns(3, 1)`
```{r backtrans}
# Linear model on original scale is poor fit
base <- ggplot(diamonds, aes(carat, price)) +
stat_bin2d() +
geom_smooth(method = "lm") +
xlab(NULL) +
ylab(NULL) +
theme(legend.position = "none")
base
# Better fit on log scale, but harder to interpret
base +
scale_x_log10() +
scale_y_log10()
# Fit on log scale, then backtransform to original.
# Highlights lack of expensive diamonds with large carats
pow10 <- scales::exp_trans(10)
base +
scale_x_log10() +
scale_y_log10() +
coord_trans(x = pow10, y = pow10)
```
### Polar coordinates with `coord_polar()`
Using polar coordinates gives rise to pie charts and wind roses (from bar geoms), and radar charts (from line geoms). Polar coordinates are often used for circular data, particularly time or direction, but the perceptual properties are not good because the angle is harder to perceive for small radii than it is for large radii. The `theta` argument determines which position variable is mapped to angle (by default, x) and which to radius.
The code below shows how we can turn a bar into a pie chart or a bullseye chart by changing the coordinate system. The documentation includes other examples. \index{Polar coordinates} \index{Coordinate systems!polar} \indexf{coord\_polar}
`r columns(3, 1)`
```{r polar}
base <- ggplot(mtcars, aes(factor(1), fill = factor(cyl))) +
geom_bar(width = 1) +
theme(legend.position = "none") +
scale_x_discrete(NULL, expand = c(0, 0)) +
scale_y_continuous(NULL, expand = c(0, 0))
# Stacked barchart
base
# Pie chart
base + coord_polar(theta = "y")
# The bullseye chart
base + coord_polar()
```
### Map projections with `coord_map()`
Maps are intrinsically displays of spherical data. Simply plotting raw longitudes and latitudes is misleading, so we must _project_ the data. There are two ways to do this with ggplot2: \index{Maps!projections} \index{Coordinate systems!map projections} \indexf{coord\_map} \indexf{coord\_quickmap} \index{mapproj}
* `coord_quickmap()` is a quick and dirty approximation that sets the aspect
ratio to ensure than 1m of latitude and 1m of longitude are the same
distance in the middle of the plot. These is a reasonable place to start
for smaller regions, and is very faster.
`r columns(2, 1, 0.75)`
```{r map-nz}
# Prepare a map of NZ
nzmap <- ggplot(map_data("nz"), aes(long, lat, group = group)) +
geom_polygon(fill = "white", colour = "black") +
xlab(NULL) + ylab(NULL)
# Plot it in cartesian coordinates
nzmap
# With the aspect ratio approximation
nzmap + coord_quickmap()
```
* `coord_map()` uses the __mapproj__ package,
<https://cran.r-project.org/package=mapproj> to do a formal map
projection. It takes the same arguments as `mapproj::mapproject()` for
controlling the projection. It is much slower than `coord_quickmap()`
because it must munch the data and transform each piece.
`r columns(3, 1)`
```{r map-world, dev = "png"}
world <- map_data("world")
worldmap <- ggplot(world, aes(long, lat, group = group)) +
geom_path() +
scale_y_continuous(NULL, breaks = (-2:3) * 30, labels = NULL) +
scale_x_continuous(NULL, breaks = (-4:4) * 45, labels = NULL)
worldmap + coord_map()
# Some crazier projections
worldmap + coord_map("ortho")
worldmap + coord_map("stereographic")
```