I want to quantify the complexity of the street network of different cities.

For each city I have the angle distribution of its streets.

polar plot of Chicago's street network

polar plot of London's street network

My hypothesis that the more complex the street network, the closer to the uniform distribution its street angle distribution. In the above plots, London's street network is much more complex than Chicago's.

To compute the distance to the uniform distribution I used the Kullback Leibler divergence and the Total Variation Distance but I get counter-intuitive results: London's KLD and TVD are higher than Chicago's, so I'm not sure these are valid for angle distributions...

Is there any specific distance I should use for this kind of data?


Edit #1: here is the code I used

import numpy as np
import osmnx as ox, pandas as pd, matplotlib.pyplot as plt
%matplotlib inline
ox.config(log_console=True, use_cache=True)

place='Chicago, USA'
G = ox.graph_from_place(place, network_type='drive')
fig, ax = ox.plot_graph(ox.project_graph(G), node_size=0)
# calculate edge bearings and visualize their frequency
G = ox.add_edge_bearings(G)
bearings = pd.Series([data['bearing'] for u, v, k, data in G.edges(keys=True, data=True)])
ax = bearings.hist(bins=30, zorder=2, alpha=0.8)
xlim = ax.set_xlim(0, 360)
ax.set_title(place + ' street network edge bearings')

def KL(a, b):
a = np.asarray(a, dtype=np.float)
b = np.asarray(b, dtype=np.float)

return np.sum(np.where(a != 0, a * np.log(a / b), 0))

def tvd(a, b):
a = np.asarray(a, dtype=np.float)
b = np.asarray(b, dtype=np.float)
return sum(abs(a-b))/2

#uniform distribution
unif_array=np.full((bearings.size), 1/float(bearings.size)) 
#normalized angle distribution

print KL(bearing_norm,unif_array)
print tvd(bearing_norm,unif_array)

# for Chicago, KL = 0.138 and TVD = 0.218
# for London, KL = 0.194 and TVD = 0.249

Edit #2: I found my mistake, I defined the uniform distribution as unif_array=np.full((bearings.size), 1/float(bearings.size)) when it should be unif_array = np.random.uniform(0,360,bearings.size)

  • $\begingroup$ You might have miscalculated. Could you explain how you have tried to compute these distances, perhaps with a small example? $\endgroup$ – whuber Sep 13 '18 at 15:08
  • $\begingroup$ Thanks for your answer! I added the code I used to compute the KLD and TVD. The angle distribution is in the array bearings, computed with the osmnx package (geoffboeing.com/2018/02/street-network-orientation) $\endgroup$ – Khanigh Sep 13 '18 at 15:27
  • $\begingroup$ Thank you. Unfortunately, without providing a (minimal) reproducible example, it doesn't get us much further towards determining what is going wrong. One thing does appear amiss: you don't seem to be looking at "directions," but only two-way orientations. This causes you to halve all the estimated probabilities, which changes the distances. These calculations also depend (strongly) on how you bin the data, so it's important to show that detail. $\endgroup$ – whuber Sep 13 '18 at 15:43
  • $\begingroup$ I added the rest of the code, but most of it is hidden in the osmnx functions. I agree with you about the two-way orientation, I will try to "fold" the distributions and work only within [0,pi]. I only bin the data for the plot, bearings contains continuous values so I don't think it's an issue. $\endgroup$ – Khanigh Sep 13 '18 at 15:55
  • $\begingroup$ It's a huge issue: how are you computing the KL distance without binning? Therein could be your problem. $\endgroup$ – whuber Sep 13 '18 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.