Reputation: 312
I have been trying to make a different this lovely flowing data visualization for some time this week but keep hitting a snag in the final implementation.
Here is the data set I'm using. I have melded it into a frame with the three key bits of information I want to display: startinglatlong, endinglatlong, and number of trips.
I got closest using the idea posted here, but two hit a snag on two items:
1) making the size of the line change based on the number of trips 2) getting the google api to allow me to call this many rows (I have 55,704 in my data set).
counts is the name of my full df, with looks like so:
head(counts)
X from_station_id.x to_station_id.x From_Station_Lat From_Station_Long End_Station_Lat End_Station_Long n eichel
1 1 5 5 41.87396 -87.62774 41.87396 -87.62774 275 41.87395806 -87.62773949
2 2 5 13 41.87396 -87.62774 41.93250 -87.65268 1 41.93250008 -87.65268082
3 3 5 14 41.87396 -87.62774 41.85809 -87.65107 12 41.858086 -87.651073
4 4 5 15 41.87396 -87.62774 41.85645 -87.65647 19 41.856453 -87.656471
5 5 5 16 41.87396 -87.62774 41.91033 -87.67252 7 41.910329 -87.672516
6 6 5 17 41.87396 -87.62774 41.90332 -87.67273 5 41.90332 -87.67273
thomas
1 41.87395806 -87.62773949
2 41.87395806 -87.62773949
3 41.87395806 -87.62773949
4 41.87395806 -87.62773949
5 41.87395806 -87.62773949
6 41.87395806 -87.62773949
Then I set about making an easier df for the function in the idea post, a la:
start<-c(counts[1:10,9])
dest<-c(counts[1:10,10])
I thought I might add in numbers into the function so I tagged on n (maybe not the best naming convention, but stick with me here).
n <- c(counts[1:10, 8])
then the route searching function:
leg <-function(start, dest){
r<- route(from=start,to=dest,mode = c("bicycling"),structure = c("legs"))
c<- geom_leg(aes(x = startLon, y = startLat, xend = endLon, yend = endLat),
alpha = 2/4, size = 2, data = r, colour = 'blue')
return (c)
}
base map:
a<-qmap('Chicago', zoom = 12, maptype="roadmap", color="bw")
now the magic:
for (n in 1:10){
#l<-leg(start[n], dest[n])
l<-leg(as.character(df[n,1]), as.character(df[n,2]))
a<-a+l
}
a
This worked.
unfortunately when I tried to run it on a larger subset it would run for a little bit and then go:
Information from URL : http://maps.googleapis.com/maps/api/directions/json? origin=41.88871604+-87.64444785&destination=41.87395806+-87.62773949&mode=bicycling&units=metric&alternatives=false&sensor=false
Error: (list) object cannot be coerced to type 'integer'
I understand from searching here and elsewhere that this can be due to Google gating api calls, and so tried adding in Sys.sleep(1), but that would break, so went to Sys.sleep(1.5) and frankly that still seems to. Even that is a pretty expensive call, given that for +55k rows you're looking at +23 hours of calls. My code was:
for (n in 1:30){
#l<-leg(start[n], dest[n])
l<-leg(as.character(df[n,1]), as.character(df[n,2]))
Sys.sleep(1.5)
a <- a + l
a}
this seemed to run but when I entered "a" I got:
Error in eval(expr, envir, enclos) : object 'startLon' not found
Finally as mentioned I'd like to visualize thicker lines for more used routes. typically I'd do this via the aes and doing something like:
geom_path(
aes(x = lon, y = lat), colour = 'red', size = n/100,
data = df, lineend = 'round'
)
so it would read column n and grant a size based on number of routes. for that to work here I need that number to bind to the directions route, so I wrote a second function like this:
leg <-function(start, dest, n){
r<- route(from=start,to=dest,mode = c("bicycling"),structure = c("route"))
c<- geom_leg(aes(x = startLon, y = startLat, xend = endLon, yend = endLat),
alpha = 2/4, size = n/10, data = r, colour = 'blue')
return (c)
}
for (n in 1:55704){
#l<-leg(start[n], dest[n])
l<-leg(as.character(df[n,1]), as.character(df[n,2]), as.numeric(df[n,3]))
Sys.sleep(1)
a <- a+l
}
This ran for a minute and then died on the error:
Error: (list) object cannot be coerced to type 'integer'
but a shorter version got tantalizingly close:
for (n in 2:6){
#l<-leg(start[n], dest[n])
l<-leg(as.character(df[n,1]), as.character(df[n,2]), as.numeric(df[n,3]))
Sys.sleep(1)
a <- a+l
}
it worked, as far as I can tell, but nothing more than like 30. Sadly the longer version just kind of runs out. basically I think that if I can get past the error message I'm almost there, I just don't want to have to spend days running the query. All help and input welcome. thank you for your time.
Upvotes: 0
Views: 2094
Reputation: 312
ok, so after a lot of noodling and modifying the above I finally settled on the looping solution that works:
leg <-function(start, dest, n){
r<- route(from=start,to=dest,mode = c("walking"),structure = c("route"))
c<- geom_path(aes(x = lon, y = lat),
alpha = 2/4, size = as.numeric(n)/500, data = r, colour = 'blue')
Sys.sleep(runif(1, 3.0, 7.5))
return (c)
}
a <- qmap('Chicago', zoom = 12, maptype = 'road', color="bw")
for (n in 101:200){
l<-leg(as.character(df[n,1]), as.character(df[n,2]),as.character(df[n,3]))
a<-a+l
}
a
this worked fairly well. the only bumps were when it the google api would reject the call. after I added the random variable sys.sleep in there it worked without a hitch. That said, I still never tried more than 150 at a go (limited my mapping to a sample of the top 10% of routes for ease of visual and for function). Finally after some happy illustrator time I ended up with a good looking map. Thanks to the community for the interest and for providing the looping idea.
Upvotes: 1