Mapping Penang hawkers using ggmap and ggplot2

This is mini-example of how to use the R package ggmap to plot your data. To get a taste of how ggmap works, why not try mapping the locations of a few recommended hawkers stalls around George Town, Penang - The Food Capital of Malaysia!

Data import

I sourced some GPS coordinates of a few hawkers from a couple of blogs I came across after a quick Google search. The ones in this example have been recommended on www.pulaupinang.com or www.what2seeonline.com by CK Lam. There are plenty more to choose from.

hawkers <- read.csv("hawkers.csv")
names(hawkers)
## [1] "Name"      "Category"  "latitude"  "longitude"
hawkers
##                                                        Name
## 1                          Stall outside Seow Fong Lye Cafe
## 2  Stall at the junction of Jln Kuala Kangsar/Lbh Kimberley
## 3                                 Kedai Kopi Sin Guat Keong
## 4                                             Magazine Road
## 5                                             Cintra Street
## 6                                      Restaurant Sulltania
## 7                             Gerai Makanan Dan Minuman Maj
## 8                                    Ah Leng Char Koay Teow
## 9                                            Kafe Heng Huat
## 10                                       Nasi Kandar Kassim
## 11                                Restoran Tajuddin Hussain
## 12                                   Nasi Kandar Line Clear
## 13                       Nasi Kandar Pelita Samudra Pertama
## 14                                    Keck Seng Coffee Shop
## 15                                     Joo Hooi Coffee Shop
## 16                                            Lok Pin Cafe.
## 17                                         One Corner Cafe.
## 18                                         Sin Yin Nam Cafe
## 19                  Stall no.17, Padang Brown Hawker Center
## 20                                    Kheng Pin Coffee Shop
## 21       Kowloon Hainan Chicken Rice, Thing Lek Coffee Shop
## 22                                       Goh Thew Chik Cafe
## 23                                          Teo Chew Cendol
##               Category latitude longitude
## 1      Chee Cheong Fun    5.417     100.3
## 2      Chee Cheong Fun    5.417     100.3
## 3      Chee Cheong Fun    5.416     100.3
## 4      Chee Cheong Fun    5.414     100.3
## 5      Chee Cheong Fun    5.418     100.3
## 6              Chapati    5.417     100.3
## 7              Chapati    5.416     100.3
## 8       Char Koay Teow    5.413     100.3
## 9       Char Koay Teow    5.417     100.3
## 10         Nasi Kandar    5.413     100.3
## 11         Nasi Kandar    5.417     100.3
## 12         Nasi Kandar    5.420     100.3
## 13         Nasi Kandar    5.416     100.3
## 14         Assam Laksa    5.416     100.3
## 15         Assam Laksa    5.417     100.3
## 16         Assam Laksa    5.416     100.3
## 17        Indian Laksa    5.422     100.3
## 18              Popiah    5.415     100.3
## 19              Popiah    5.414     100.3
## 20 Hainan Chicken Rice    5.421     100.3
## 21 Hainan Chicken Rice    5.416     100.3
## 22 Hainan Chicken Rice    5.419     100.3
## 23              Cendol    5.417     100.3

Importing your base map

Once you have your data ready we need to import a base map into R, onto which we can plot our data. In this example I have chosen to use a base map from Stamen. See ?get_map for more details and experiment with many other map styles (e.g. Google Maps).

We can start with using a basic square map, centered on George Town, Penang.

require(ggmap)
require(mapproj)
pg <- get_map(location='George Town, Penang',  
              zoom = 14,       # ranges from 0 (whole world) to 21 (building)
              source='stamen', # try 'google' or 'osm'      
              maptype='toner', 
              color='color'
              ) 

# the ggmap() function will convert your map data into a ggplot object
# the agruments to include your data at this stage are not essential, but 
# can make it easier to add layers (such as 'geoms') later on 
PG <- ggmap(pg, extent='panel', 
            base_layer=ggplot(hawkers, aes(x=longitude, y=latitude))
            )
print(PG)

plot of chunk ggmap_square

Looks like a decent start.

Plotting data

To plot our data we simply overlay a “geom” using ggplot2

PG <- PG + geom_point(color = "red", size = 4)
print(PG)

plot of chunk geom_point

This looks pretty good, but let's say we want to focus in a little more around the areas where most of the data points are, so that we can actually see what roads our hawkers are on. We can set the map bounds using the 'location' argument in the get_map() function*. You can set this manually, but the function make_bbox() is a neat and easy way to find the max and min of your geocoordinates.

*not if Google is used as a source, for some reason

lon <- hawkers$longitude
lat <- hawkers$latitude
box <- make_bbox(lon, lat, f = 0.1)
box
##    left  bottom   right     top 
## 100.315   5.412 100.341   5.422
# as before, we download our map data and convert it into a 'gg' object.
# note that because we are explicitly setting our map boundaries,
# adjusting the zoom in this case will change the resolution of the base
# map not the 'zoom' per se (likely to add further details, too)
pg <- get_map(location = box, zoom = 16, source = "stamen", maptype = "toner", 
    color = "color")

PG <- ggmap(pg, extent = "panel", base_layer = ggplot(hawkers, aes(x = longitude, 
    y = latitude)))

# here is where we can change the 'aesthetics' of our points
PG <- PG + geom_point(aes(color = Category), size = 5, alpha = 0.8)

# then a little bit of cosmetic work...  change category colors, titles,
# etc
PG <- PG + scale_colour_brewer(palette = "Set1")

PG <- PG + labs(title = "Recommended hawkers around George Town, Penang", x = "Longitude", 
    y = "Latitude")

PG <- PG + theme(plot.title = element_text(hjust = 0, vjust = 1, face = c("bold")), 
    legend.position = "right")


print(PG)

plot of chunk ggmap

And we are done! Now start working your way through all these delicous food stalls…