0

This code below creates map of UK postcodes using ggplot, however leaves some of the parts white/missing from the map, could you please advise how to make sure that whole map is filled and that the postcode areas have a border ? Thanks.

MAP OF UK from the below code

rm(list=ls())
library(tidyverse)
library(maptools)
library(raster)
library(plotrix)
library(ggrepel)


df2016 <- read.table(stringsAsFactors=FALSE, header=TRUE, text="
                     name value amount
                     LD 1   3
                     ZE 1   2
                     WS 0.79    19
                     ML 0.75    12
                     HS 0.75    4
                     TQ 0.74    38
                     WN 0.73    15
                     CA 0.71    28
                     HU 0.7 33
                     FY 0.69    16
                     HG 0.69    16
                     IV 0.68    19
                     DL 0.68    25
                     CB 0.68    115
                     TS 0.67    46
                     IP 0.67    87
                     AB 0.67    66
                     NP 0.67    45
                     FK 0.67    18
                     IM 0.67    9
                     SM 0.66    50
                     HD 0.66    32
                     EN 0.66    61
                     CO 0.65    52
                     ME 0.65    54
                     PE 0.64    266
                     EX 0.64    81
                     WV 0.63    49
                     JE 0.63    24
                     NE 0.62    148
                     YO 0.62    47
                     DE 0.62    78
                     LN 0.61    36
                     SN 0.61    109
                     IG 0.6 63
                     NR 0.6 90
                     SP 0.59    37
                     BA 0.59    93
                     UB 0.59    127
                     TN 0.59    95
                     BT 0.59    180
                     BD 0.59    51
                     HP 0.59    126
                     TA 0.59    46
                     PO 0.58    113
                     DH 0.58    55
                     WD 0.58    102
                     BH 0.57    96
                     DG 0.57    14
                     CV 0.57    225
                     RG 0.57    255
                     BN 0.56    158
                     DY 0.56    48
                     HA 0.56    148
                     W  0.56    359
                     WA 0.56    77
                     DA 0.55    38
                     CT 0.55    62
                     GU 0.55    231
                     RH 0.55    132
                     BL 0.55    33
                     HX 0.55    11
                     BS 0.54    184
                     SS 0.54    46
                     EH 0.54    185
                     DT 0.54    37
                     G  0.54    137
                     B  0.54    283
                     LU 0.54    41
                     NG 0.54    97
                     OX 0.53    208
                     S  0.53    179
                     CM 0.53    100
                     DD 0.53    17
                     GL 0.53    87
                     AL 0.53    89
                     HR 0.53    38
                     LS 0.52    122
                     TF 0.52    21
                     RM 0.52    44
                     SL 0.52    155
                     MK 0.52    136
                     SY 0.52    46
                     DN 0.52    81
                     N  0.52    191
                     M  0.52    226
                     SR 0.52    29
                     SK 0.52    64
                     BB 0.51    140
                     KY 0.51    41
                     WF 0.51    51
                     PR 0.51    63
                     L  0.51    81
                     KT 0.5 185
                     CF 0.5 118
                     ST 0.5 84
                     TR 0.5 46
                     CW 0.5 44
                     TD 0.5 12
                     P  0.5 2
                     SW 0.5 317
                     LL 0.49    49
                     CH 0.49    43
                     E  0.49    275
                     EC 0.48    364
                     PA 0.48    27
                     SO 0.48    157
                     CR 0.48    84
                     PL 0.48    61
                     SG 0.47    59
                     KA 0.47    15
                     LA 0.47    43
                     SA 0.46    78
                     LE 0.46    194
                     TW 0.45    125
                     OL 0.44    41
                     SE 0.44    297
                     NN 0.43    143
                     NW 0.42    236
                     WC 0.41    138
                     WR 0.38    73
                     BR 0.37    62
                     GY 0.26    35
                     PH 0.23    13
                     ")

#df2016$amount <- NULL
df2016$name <- as.character(df2016$name)


# Download a shapefile of postal codes into your working directory
download.file(
  "http://www.opendoorlogistics.com/wp-content/uploads/Data/UK-postcode-boundaries-Jan-2015.zip",
  "postal_shapefile"
)


# Unzip the shapefile
unzip("postal_shapefile")

# Read the shapefile
postal <- readShapeSpatial("./Distribution/Areas")

postal.df <- fortify(postal, region = "name")

# Join your data to the shapefile
colnames(postal.df)[colnames(postal.df) == "id"] <- "name"

postal.df <- raster::merge(postal.df, df2016, by = "name")

postal.df$value[is.na(postal.df$value)] <- 0.50

# Get centroids of spatialPolygonDataFrame and convert to dataframe
# for use in plotting  area names. 

postal.centroids.df <- data.frame(long = coordinates(postal)[, 1], 
                                         lat = coordinates(postal)[, 2],
                                  id=postal$name)


p <- ggplot(postal.df, aes(x = long, y = lat, group = group)) + geom_polygon(aes(fill = cut(value,5))) + 
  geom_text_repel(data = postal.centroids.df, aes(label = id, x = long, y = lat, group = id), size = 3, check_overlap = T) + 
  labs(x=" ", y=" ") + 
  theme_bw() + scale_fill_brewer('Success Rate 2016', palette  = 15) + 
  coord_map() + 
  theme(panel.grid.minor=element_blank(), panel.grid.major=element_blank()) + 
  theme(axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank()) + 
  theme(panel.border = element_blank())
p
ThomasJohnson
  • 167
  • 1
  • 10
  • In my experience with `maptools` and `ggplot`, I have found that converting all `NA`'s to 0's will allow the polygon to be filled instead of missed plotting. My NA's came from mismatch in merging. You can then change your color scheme to make zeros a color other than white. I know you have code to account for that, but might want to check again in case they are `""` or `" "` characters as well. – Geochem B Jul 21 '17 at 14:32

2 Answers2

1

Try arranging the postal code by name or number just before plotting

postal.centroids.df %>%
arrange(id)

My county maps of the US did the same thing when they weren't in order. If that doesn't work try by lat or long as well.

Geochem B
  • 418
  • 3
  • 13
  • Unfortunately doesn't work here. Tried to arrange by each value. :/ – ThomasJohnson Jul 21 '17 at 15:00
  • What about if you also arrange the `postal.df`? I've had the same problem but I joined all the data into one data.frame, you may need to order both data frames. The issue seemd to be that when plotting if the map had elements out of "order" (whatever that means) that the weird fill pattern was because the groups where plotting based on the ggplot arrangement, which was in different patterns than the df. Theres another [post](https://stackoverflow.com/questions/26540955/maps-ggplot2-fill-by-state-is-missing-certain-areas-on-the-map) identifying the merge order as the problem. – Geochem B Jul 21 '17 at 15:25
  • The issue was solved by using left_join from dplyr - you were right here, merge kind of put the data out of order. Thanks for help! – ThomasJohnson Jul 21 '17 at 20:59
  • Could you post the code? Would like to know where the issue was. – Geochem B Jul 21 '17 at 21:02
  • Sure, please find it below and thanks for suggestions! :) – ThomasJohnson Jul 21 '17 at 21:23
1

Solution was to use left_join from dplyr instead of merge:

rm(list=ls())
library(tidyverse)
library(maptools)
library(raster)
library(plotrix)
library(ggrepel)


df2016 <- read.table(stringsAsFactors=FALSE, header=TRUE, text="
                     name value amount
                     LD 1   3
                     ZE 1   2
                     WS 0.79    19
                     ML 0.75    12
                     HS 0.75    4
                     TQ 0.74    38
                     WN 0.73    15
                     CA 0.71    28
                     HU 0.7 33
                     FY 0.69    16
                     HG 0.69    16
                     IV 0.68    19
                     DL 0.68    25
                     CB 0.68    115
                     TS 0.67    46
                     IP 0.67    87
                     AB 0.67    66
                     NP 0.67    45
                     FK 0.67    18
                     IM 0.67    9
                     SM 0.66    50
                     HD 0.66    32
                     EN 0.66    61
                     CO 0.65    52
                     ME 0.65    54
                     PE 0.64    266
                     EX 0.64    81
                     WV 0.63    49
                     JE 0.63    24
                     NE 0.62    148
                     YO 0.62    47
                     DE 0.62    78
                     LN 0.61    36
                     SN 0.61    109
                     IG 0.6 63
                     NR 0.6 90
                     SP 0.59    37
                     BA 0.59    93
                     UB 0.59    127
                     TN 0.59    95
                     BT 0.59    180
                     BD 0.59    51
                     HP 0.59    126
                     TA 0.59    46
                     PO 0.58    113
                     DH 0.58    55
                     WD 0.58    102
                     BH 0.57    96
                     DG 0.57    14
                     CV 0.57    225
                     RG 0.57    255
                     BN 0.56    158
                     DY 0.56    48
                     HA 0.56    148
                     W  0.56    359
                     WA 0.56    77
                     DA 0.55    38
                     CT 0.55    62
                     GU 0.55    231
                     RH 0.55    132
                     BL 0.55    33
                     HX 0.55    11
                     BS 0.54    184
                     SS 0.54    46
                     EH 0.54    185
                     DT 0.54    37
                     G  0.54    137
                     B  0.54    283
                     LU 0.54    41
                     NG 0.54    97
                     OX 0.53    208
                     S  0.53    179
                     CM 0.53    100
                     DD 0.53    17
                     GL 0.53    87
                     AL 0.53    89
                     HR 0.53    38
                     LS 0.52    122
                     TF 0.52    21
                     RM 0.52    44
                     SL 0.52    155
                     MK 0.52    136
                     SY 0.52    46
                     DN 0.52    81
                     N  0.52    191
                     M  0.52    226
                     SR 0.52    29
                     SK 0.52    64
                     BB 0.51    140
                     KY 0.51    41
                     WF 0.51    51
                     PR 0.51    63
                     L  0.51    81
                     KT 0.5 185
                     CF 0.5 118
                     ST 0.5 84
                     TR 0.5 46
                     CW 0.5 44
                     TD 0.5 12
                     P  0.5 2
                     SW 0.5 317
                     LL 0.49    49
                     CH 0.49    43
                     E  0.49    275
                     EC 0.48    364
                     PA 0.48    27
                     SO 0.48    157
                     CR 0.48    84
                     PL 0.48    61
                     SG 0.47    59
                     KA 0.47    15
                     LA 0.47    43
                     SA 0.46    78
                     LE 0.46    194
                     TW 0.45    125
                     OL 0.44    41
                     SE 0.44    297
                     NN 0.43    143
                     NW 0.42    236
                     WC 0.41    138
                     WR 0.38    73
                     BR 0.37    62
                     GY 0.26    35
                     PH 0.23    13
                     ")


# Download a shapefile of postal codes into your working directory
download.file(
  "http://www.opendoorlogistics.com/wp-content/uploads/Data/UK-postcode-boundaries-Jan-2015.zip",
  "postal_shapefile"
)


# Unzip the shapefile
unzip("postal_shapefile")

# Read the shapefile
postal <- readShapeSpatial("./Distribution/Areas")

postal.df <- fortify(postal, region = "name")

# Join your data to the shapefile
colnames(postal.df)[colnames(postal.df) == "id"] <- "name"

library(dplyr)
test <- left_join(postal.df, df2016, by = "name", copy = FALSE)

#postal.df <- raster::merge(postal.df, df2016, by = "name")

test$value[is.na(test$value)] <- 0.50

# for use in plotting  area names. 

postal.centroids.df <- data.frame(long = coordinates(postal)[, 1], 
                                  lat = coordinates(postal)[, 2],
                                  id=postal$name)


p <- ggplot(test, aes(x = long, y = lat, group = group)) + geom_polygon(aes(fill = cut(value,5))) + 
  geom_text_repel(data = postal.centroids.df, aes(label = id, x = long, y = lat, group = id), size = 3, check_overlap = T) + 
  labs(x=" ", y=" ") + 
  theme_bw() + scale_fill_brewer('Success Rate 2016', palette  = 15) + 
  coord_map() + 
  theme(panel.grid.minor=element_blank(), panel.grid.major=element_blank()) + 
  theme(axis.ticks = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank()) + 
  theme(panel.border = element_blank())
p
ThomasJohnson
  • 167
  • 1
  • 10