SF OpenData - Parking meter data

Where are the Parking meters in San Fransisco?

To find data on the SF OpenData website you can click on one of the 10 topics provided or you can search. To find data about Parking meters in SF, search on Parking meters. The first result should be a link to the Parking meters dataset.

The SF OpenData website now has maps. You need to create an account of the website to save you plots. Here is a link to a map that I made of Where are the Parking meters?

Now we are going to use the provided API to download the data into R. To get the API Endpoint, from the spreadsheet, click on Export and copy the web link.

# install.packages("RSocrata)
library("RSocrata")
df <- read.socrata("https://data.sfgov.org/resource/yuti-t9a7.json")
head(df)

Note the the location columns have been read in as char values. These should be numeric. First we will transform them into numeric columns. We will change smart_mete to a factor, which will let us color the map with two colors. Note that sapply is used to check the classes of the columns in the dataframe.

df <- transform(df, location.longitude = as.numeric(location.longitude), 
               location.latitude = as.numeric(location.latitude), 
               smart_mete = as.factor(smart_mete))
sapply(df, class)
                  ms_id              streetname              smart_mete              ms_spaceid 
            "character"             "character"                "factor"             "character" 
             meter_type              street_num               cap_color              jurisdicti 
            "character"             "character"             "character"             "character" 
                post_id              sfparkarea              on_off_str       location.latitude 
            "character"             "character"             "character"               "numeric" 
location.needs_recoding      location.longitude                  osp_id                ratearea 
            "character"               "numeric"             "character"             "character" 
             street_seg              activesens 
            "character"             "character" 

To simplify the dataframe we will take a subset of the columns of the original dataframe: type, latitude, and longitude. We will simplify the names of the variables/columns.

df.meters <- df[,c(3,12,14)]
names(df.meters) <- c("type","latitude","longitude")
sapply(df.meters, class)
     type  latitude longitude 
 "factor" "numeric" "numeric" 

Now using the package ggmap we get a map and then plot the locations of the Parking meters on the map.

#install.packages("ggmap")
library(ggmap)
Loading required package: ggplot2
Google Maps API Terms of Service: http://developers.google.com/maps/terms.
Please cite ggmap if you use it: see citation('ggmap') for details.
m <- get_map("San Fransisco", zoom=13, maptype="toner", source="stamen")
Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Fransisco&zoom=13&size=640x640&scale=2&maptype=terrain&sensor=false
Information from URL : http://maps.googleapis.com/maps/api/geocode/json?address=San%20Fransisco&sensor=false
Map from URL : http://tile.stamen.com/toner/13/1309/3165.png
Map from URL : http://tile.stamen.com/toner/13/1310/3165.png
Map from URL : http://tile.stamen.com/toner/13/1311/3165.png
Map from URL : http://tile.stamen.com/toner/13/1309/3166.png
Map from URL : http://tile.stamen.com/toner/13/1310/3166.png
Map from URL : http://tile.stamen.com/toner/13/1311/3166.png
Map from URL : http://tile.stamen.com/toner/13/1309/3167.png
Map from URL : http://tile.stamen.com/toner/13/1310/3167.png
Map from URL : http://tile.stamen.com/toner/13/1311/3167.png
# available colors for ggplot2  http://sape.inf.usi.ch/quick-reference/ggplot2/colour
ggmap(m, base_layer = ggplot(aes(x = longitude, y = latitude), data = df.meters))  + geom_point(color="dark blue")

ggmap(m, base_layer = ggplot(aes(x = longitude, y = latitude, colour=type), data = df.meters))  + geom_point()

Subsetting.

df.meters.smart <- subset(df.meters, type=="Y")
ggmap(m, base_layer = ggplot(aes(x = longitude, y = latitude), data = df.meters.smart))  + geom_point(color="turquoise2")

df.meters.not.smart <- subset(df.meters, type=="N")
ggmap(m, base_layer = ggplot(aes(x = longitude, y = latitude), data = df.meters.not.smart))  + geom_point(color="indianred2")

LS0tCnRpdGxlOiAiUGFya2luZyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgW1NGIE9wZW5EYXRhXShodHRwczovL2RhdGEuc2Znb3Yub3JnKSAtIFBhcmtpbmcgbWV0ZXIgZGF0YQoKKipXaGVyZSBhcmUgdGhlIFBhcmtpbmcgbWV0ZXJzIGluIFNhbiBGcmFuc2lzY28/KioKClRvIGZpbmQgZGF0YSBvbiB0aGUgW1NGIE9wZW5EYXRhXShodHRwczovL2RhdGEuc2Znb3Yub3JnKSB3ZWJzaXRlIHlvdSBjYW4gY2xpY2sgb24gb25lIG9mIHRoZSAxMCB0b3BpY3MgcHJvdmlkZWQgb3IgeW91IGNhbiBzZWFyY2guICBUbyBmaW5kIGRhdGEgYWJvdXQgUGFya2luZyBtZXRlcnMgaW4gU0YsIHNlYXJjaCBvbiAqKlBhcmtpbmcgbWV0ZXJzKiouICBUaGUgZmlyc3QgcmVzdWx0IHNob3VsZCBiZSBhIGxpbmsgdG8gdGhlIFBhcmtpbmcgbWV0ZXJzIGRhdGFzZXQuCgpUaGUgU0YgT3BlbkRhdGEgd2Vic2l0ZSBub3cgaGFzIG1hcHMuICBZb3UgbmVlZCB0byBjcmVhdGUgYW4gYWNjb3VudCBvZiB0aGUgd2Vic2l0ZSB0byBzYXZlIHlvdSBwbG90cy4gIEhlcmUgaXMgYSBsaW5rIHRvIGEgbWFwIHRoYXQgSSBtYWRlIG9mIFtXaGVyZSBhcmUgdGhlIFBhcmtpbmcgbWV0ZXJzXShodHRwczovL2RhdGEuc2Znb3Yub3JnL1RyYW5zcG9ydGF0aW9uL1doZXJlLWFyZS10aGUtUGFya2luZy1tZXRlcnMtL3l1dGktdDlhNyk/CgpOb3cgd2UgYXJlIGdvaW5nIHRvIHVzZSB0aGUgcHJvdmlkZWQgQVBJIHRvIGRvd25sb2FkIHRoZSBkYXRhIGludG8gUi4gIFRvIGdldCB0aGUgKipBUEkgRW5kcG9pbnQqKiwgZnJvbSB0aGUgc3ByZWFkc2hlZXQsIGNsaWNrIG9uICoqRXhwb3J0KiogYW5kIGNvcHkgdGhlIHdlYiBsaW5rLgoKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcygiUlNvY3JhdGEpCgpsaWJyYXJ5KCJSU29jcmF0YSIpCgpkZiA8LSByZWFkLnNvY3JhdGEoImh0dHBzOi8vZGF0YS5zZmdvdi5vcmcvcmVzb3VyY2UveXV0aS10OWE3Lmpzb24iKQpgYGAKCmBgYHtyfQpoZWFkKGRmKQpgYGAKCk5vdGUgdGhlIHRoZSAqbG9jYXRpb24qIGNvbHVtbnMgaGF2ZSBiZWVuIHJlYWQgaW4gYXMgKmNoYXIqIHZhbHVlcy4gIFRoZXNlIHNob3VsZCBiZSBudW1lcmljLiAgRmlyc3Qgd2Ugd2lsbCB0cmFuc2Zvcm0gdGhlbSBpbnRvIG51bWVyaWMgY29sdW1ucy4gIFdlIHdpbGwgY2hhbmdlICoqc21hcnRfbWV0ZSoqIHRvIGEgZmFjdG9yLCB3aGljaCB3aWxsIGxldCB1cyBjb2xvciB0aGUgbWFwIHdpdGggdHdvIGNvbG9ycy4gIE5vdGUgdGhhdCBzYXBwbHkgaXMgdXNlZCB0byBjaGVjayB0aGUgY2xhc3NlcyBvZiB0aGUgY29sdW1ucyBpbiB0aGUgZGF0YWZyYW1lLgoKYGBge3J9CmRmIDwtIHRyYW5zZm9ybShkZiwgbG9jYXRpb24ubG9uZ2l0dWRlID0gYXMubnVtZXJpYyhsb2NhdGlvbi5sb25naXR1ZGUpLCAKICAgICAgICAgICAgICAgbG9jYXRpb24ubGF0aXR1ZGUgPSBhcy5udW1lcmljKGxvY2F0aW9uLmxhdGl0dWRlKSwgCiAgICAgICAgICAgICAgIHNtYXJ0X21ldGUgPSBhcy5mYWN0b3Ioc21hcnRfbWV0ZSkpCnNhcHBseShkZiwgY2xhc3MpCmBgYAoKVG8gc2ltcGxpZnkgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHRha2UgYSBzdWJzZXQgb2YgdGhlIGNvbHVtbnMgb2YgdGhlIG9yaWdpbmFsIGRhdGFmcmFtZTogdHlwZSwgbGF0aXR1ZGUsIGFuZCBsb25naXR1ZGUuICBXZSB3aWxsIHNpbXBsaWZ5IHRoZSBuYW1lcyBvZiB0aGUgdmFyaWFibGVzL2NvbHVtbnMuCgpgYGB7cn0KZGYubWV0ZXJzIDwtIGRmWyxjKDMsMTIsMTQpXQoKbmFtZXMoZGYubWV0ZXJzKSA8LSBjKCJ0eXBlIiwibGF0aXR1ZGUiLCJsb25naXR1ZGUiKQoKc2FwcGx5KGRmLm1ldGVycywgY2xhc3MpCmBgYAoKTm93IHVzaW5nIHRoZSBwYWNrYWdlICoqZ2dtYXAqKiB3ZSBnZXQgYSBtYXAgYW5kIHRoZW4gcGxvdCB0aGUgbG9jYXRpb25zIG9mIHRoZSBQYXJraW5nIG1ldGVycyBvbiB0aGUgbWFwLgoKYGBge3J9CiNpbnN0YWxsLnBhY2thZ2VzKCJnZ21hcCIpCgpsaWJyYXJ5KGdnbWFwKQoKbSA8LSBnZXRfbWFwKCJTYW4gRnJhbnNpc2NvIiwgem9vbT0xMywgbWFwdHlwZT0idG9uZXIiLCBzb3VyY2U9InN0YW1lbiIpCmBgYAoKYGBge3J9CiMgYXZhaWxhYmxlIGNvbG9ycyBmb3IgZ2dwbG90MiAgaHR0cDovL3NhcGUuaW5mLnVzaS5jaC9xdWljay1yZWZlcmVuY2UvZ2dwbG90Mi9jb2xvdXIKCmdnbWFwKG0sIGJhc2VfbGF5ZXIgPSBnZ3Bsb3QoYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIGRhdGEgPSBkZi5tZXRlcnMpKSAgKyBnZW9tX3BvaW50KGNvbG9yPSJkYXJrIGJsdWUiKQpgYGAKCmBgYHtyfQpnZ21hcChtLCBiYXNlX2xheWVyID0gZ2dwbG90KGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIGNvbG91cj10eXBlKSwgZGF0YSA9IGRmLm1ldGVycykpICArIGdlb21fcG9pbnQoKQpgYGAKClN1YnNldHRpbmcuCgpgYGB7cn0KZGYubWV0ZXJzLnNtYXJ0IDwtIHN1YnNldChkZi5tZXRlcnMsIHR5cGU9PSJZIikKYGBgCgoKYGBge3J9CmdnbWFwKG0sIGJhc2VfbGF5ZXIgPSBnZ3Bsb3QoYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSksIGRhdGEgPSBkZi5tZXRlcnMuc21hcnQpKSAgKyBnZW9tX3BvaW50KGNvbG9yPSJ0dXJxdW9pc2UyIikKYGBgCgpgYGB7cn0KZGYubWV0ZXJzLm5vdC5zbWFydCA8LSBzdWJzZXQoZGYubWV0ZXJzLCB0eXBlPT0iTiIpCmBgYAoKCmBgYHtyfQpnZ21hcChtLCBiYXNlX2xheWVyID0gZ2dwbG90KGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUpLCBkYXRhID0gZGYubWV0ZXJzLm5vdC5zbWFydCkpICArIGdlb21fcG9pbnQoY29sb3I9ImluZGlhbnJlZDIiKQpgYGAK