-
Notifications
You must be signed in to change notification settings - Fork 9
/
demo.Rmd
202 lines (161 loc) · 7.7 KB
/
demo.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
---
output:
html_document:
highlight: kate
theme: spacelab
pdf_document:
highlight: haddock
number_sections: yes
html_document:
highlight: kate
theme: spacelab
---
A Front End For the Rcartogram Package
========================================================
This demonstrates the *getcartr* package. Firstly, make sure you have the `Rcartogram` package installed. This can be downloaded from http://www.omegahat.org/Rcartogram/ .
Next - if you haven't already done so, install this package from github - make sure `devtools` is installed in R, then enter
`library(devtools);install_github('chrisbrunsdon/getcartr',subdir='getcartr')`.
Now you are ready to use the package:
Now load the package:
```{r,message=FALSE,warning=FALSE}
library(getcartr)
```
`quick.carto` gives you a cartogram very quickly:
```{r fig.width=11, fig.height=7}
data(georgia)
georgia.carto <- quick.carto(georgia,georgia2$TotPop90, blur=1)
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
plot(georgia2)
title("Original Projection")
plot(georgia.carto)
title("Cartogram Projection")
```
and plot the transformation mesh:
```{r fig.width=7, fig.height=7}
# Load an example SpatialPolygonsDataFrame from GISTools
data(georgia)
# Create the cartogram. TotPop90 contains 1990 county populations
# "georgia2" is used as it has a plane projection coordinate system
georgia.carto <- quick.carto(georgia2,georgia2$TotPop90)
# Draw the dispersion plot
dispersion(georgia.carto, col='darkred')
```
and apply the cartogram transform to new sets of points:
```{r fig.width=11, fig.height=7}
# Create a set of 25 points from northwest to southeast corners
xl <- seq(1419424,939220.7,l=25)
yl <- seq(905508,1405900,l=25)
pset <- readWKT(paste("MULTIPOINT(",paste(apply(cbind(xl,yl),1,function(x) paste("(",x[1],x[2],")")),collapse=","),")"))
#' # Transform it
pset.carto <- warp.points(pset,georgia.carto)
# Plot the original points
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
plot(georgia2,border='grey'); plot(pset, add=T, col='red')
title('Original projection')
# Plot in cartogram space
plot(georgia.carto,border='grey'); plot(pset.carto, add=T, col='red')
title('Cartogram projection')
```
or lines:
```{r fig.width=11, fig.height=7}
# Create a line from southwest to northeast corners, with 100 segments
xl <- seq(939220.7,1419424,l=100)
yl <- seq(905508,1405900,l=100)
aline <- readWKT(paste("LINESTRING(",paste(apply(cbind(xl,yl),1,function(x) paste(x[1],x[2])),collapse=","),")"))
# Transform it
aline.carto <- warp.lines(aline,georgia.carto)
# Plot the original line
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
plot(georgia2,border='grey'); plot(aline, add=T, col='red')
title('Original projection')
# Plot in cartogram space
plot(georgia.carto,border='grey'); plot(aline.carto, add=T, col='red')
title('Cartogram projection')
```
... or areas.
```{r fig.width=11, fig.height=7}
# Create a pseudocircle with 100 segments
xl <- cos(seq(0,2*pi,l=100))*100000 + 1239348
yl <- sin(seq(0,2*pi,l=100))*100000 + 1093155
circ <- readWKT(paste("MULTIPOLYGON(((",paste(apply(cbind(xl,yl),1,function(x) sprintf("%7.0f %7.0f",x[1],x[2])),collapse=","),")))"))
#' # Transform it
circ.carto <- warp.polys(circ,georgia.carto)
# Plot the original circle
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
plot(georgia2,border='grey'); plot(circ, add=T, col=rgb(1,0,0,0.4), border=NA)
title('Original projection')
# Plot in cartogram space
plot(georgia.carto,border='grey'); plot(circ.carto, add=T, col=rgb(1,0,0,0.4), border=NA)
title('Cartogram projection')
```
# Alternative approach
Use the `carto.transform` function to create a new *function* to apply the cartogram transform to any shapefile. This function automatically determines whether the input object is `SpatialPolygons*`, `SpatialLines*` or `SpatialPoints*`. Here the Newhaven data in `GISTools` will be used:
```{r fig.width=11, fig.height=7}
# Get the newhaven data
require(GISTools)
data(newhaven)
# Plot the untransformed data
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
plot(blocks) # Census blocks
plot(roads,col='lightgrey',add=TRUE) # Roads
plot(burgres.f,col='darkred',pch=16,add=TRUE) # Forced entry burglaries
# Create the cartogram transform function
# The 'res' here gives the resolution of the cartogram interpolation grid
# - default is 128, so here we have 4 times that resolution. Slower but
# more accurate...
to.carto <- carto.transform(blocks,blocks$POP1990,res=512)
# Now create a cartogram version of the map
# Plot the blocks carto
plot(to.carto(blocks))
# Add roads, transformed to cartogram space
plot(to.carto(roads),add=TRUE,col='lightgrey')
# Add forced entry residential burglaries, transformed to cartogram space
plot(to.carto(burgres.f),add=TRUE,col='darkred',pch=16)
```
# Diagnostics
Next, a few visual diagnostics. Firstly, superimpose the dispersion diagram on the cartogram itself. Secondly, plot the cartogram variable against the actual area of the corresponding polygon in the cartogram. Ideally these should lie on a straight line going through the origin.
```{r fig.width=11, fig.height=7}
# Superimpose dispersion diagram on cartogram:
par(mfrow=c(1,2),mar=c(0.5,0.5,3,0.5))
blocks.cart <- to.carto(blocks)
plot(blocks.cart)
dispersion(blocks.cart,col=rgb(0.5,0,0,0.3),add=TRUE)
# Scatterplot the cartogram variable against actual zone area
par(mar=c(5,5,5,5))
cartvar <- blocks$POP1990
cartarea <- poly.areas(blocks.cart)
plot(cartvar,cartarea,
xlab='Population',ylab='Cartogram "Pixels"')
abline(lm(cartarea~0+cartvar),lty=2)
```
Finally, a numerical diagnostic also exists. Based on the idea that, from the definition, an ideal cartogram transform will create a set of zones whose area is proportional to the chosen statistical variable associated with each zone. Thus, as stated above, these two quantities, when plotted, should lie on a straight line passing through the origin. Thus, the $R^2$ statistic obtained when regressing one on the other **without an intercept** should be equal to one. If $x_i$ is the area of zone $i$ in cartogram space, and $y_i$ is the associated value of the cartogram variable, then the estimated slope of the line, $\hat{s}$ is given by
$$ \hat{s} = \frac{\sum_i x_iy_i}{\sum x_i^2} $$
and then
$$ R^2 = \frac{\sum_i{\left( \hat{s} x_i \right)}^2}{\sum_i{\left( \hat{s} x_i \right)}^2 + \sum_i{\left( y_i - \hat{s} x_i \right)}^2} $$
The `cart.r2` function computes this quantity:
```{r}
# Check out the r-squared for the cartogram just made...
cart.r2(blocks.cart,blocks$POP1990)
# Now try it for different resolutions
result = NULL
res.list <- c(128,192,256,320,384)
for (r in res.list) result <- c(result,
cart.r2(quick.carto(blocks,res=r,blocks$POP1990,thresh=0.1),blocks$POP1990))
result <- cbind(res.list,result)
result
```
and show this as a graph
```{r}
plot(result,xlab='Resolution',ylab=expression(R^2),type='b')
```
The straight line fitted through the origin can also be used as a basis to identify whether areas are under or over represented, by considering the residual value $y_i - \hat{s}x_i$ for each zone $i$. Positive values of this suggest under representation, and negative values suggest over representation (although the $R^2$ figures above suggest the degree of error is very small). These residuals can be computed using the `cart.resids` function, and then mapped. Here they are mapped in both cartogram space and the standard map projection.
```{r fig.width=11, fig.height=7}
par(mfrow=c(1,2),mar=c(1,1,1,1))
resids <- cart.resids(blocks.cart,blocks$POP1990)
shades <- auto.shading(c(resids,-resids),n=5,col=brewer.pal(5,'RdBu'))
choropleth(blocks,resids,shading=shades)
title('Discrepancy (Cartogram Pixels) - Standard Projection')
choropleth(blocks.cart,resids,shading=shades)
choro.legend(100,100,shades)
title('Discrepancy (Cartogram Pixels) - Cartogram Projection')
```