Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Find nearest POI to POI from another category #146

Open
majdal opened this issue Sep 8, 2020 · 6 comments
Open

[Question] Find nearest POI to POI from another category #146

majdal opened this issue Sep 8, 2020 · 6 comments

Comments

@majdal
Copy link

majdal commented Sep 8, 2020

Hello - Thanks for the great work on this package!

I just spent a couple of hours digging through the code of pandana to find an answer to this question, but couldn't find any solutions. I'd appreciate any help!

The problem that I have is what follow: I have a number of buildings (node POIs), and a number of schools (node POIs). I want to find the nearest school to each building, using the network from OSM.

It's possible to accomplish this through a nearest neighbour look-ups using scipy's KDTree or scikit-learn's BallTree, but those provide euclidian or great circle distances, and what I want is the network distance. Is there a suggested way to go about this using pandana?

In my digging, I found the find_all_nearest_pois function, but that gives me the nearest POI for the network's nodes, not the nodes from a category that I specify.

Many thanks!

@smmaurer
Copy link
Member

smmaurer commented Sep 8, 2020

Hi @majdal,

My guess is that the brute force approach of calculating the distance from every building to every school -- and then selecting the closest one -- would actually work pretty well here.

Since the recent v0.5 update, point-to-point network distances are super fast to calculate. Section 2 of this notebook has some code examples: Pandana-demo.ipynb

It's on our wish list to expose direct functionality like you're describing, but right now I think it's buried deep inside the graph traversal algorithms.

Something here might be helpful too: shortest-paths.ipynb. This notebook uses NetworkX instead of Pandana to calculate distances, which guarantees you're getting exactly the shortest path but is much slower. The last cell has an example of selecting the closest destination for each origin.

One final suggestion -- if there are so many buildings (millions, say) that the pure brute-force approach is too slow, you could add a preprocessing step where you use euclidean distances to identify a handful of candidate schools for each building, and then use Pandana to figure out which has the shortest network distance.

Hope this helps, and best of luck!

@smmaurer
Copy link
Member

smmaurer commented Sep 8, 2020

Actually, it might be easier and/or faster to just calculate the closest school to each network node, and then match the buildings that you're interested in to the relevant nodes.

The function you linked to is actually in the underlying C++ code -- here's the corresponding Python function: http://udst.github.io/pandana/network.html#pandana.network.Network.nearest_pois

@fscottfoti
Copy link
Contributor

fscottfoti commented Sep 8, 2020 via email

@majdal
Copy link
Author

majdal commented Sep 9, 2020

Thanks @smmaurer and @fscottfoti for your very quick replies!

I like Sam's suggestion, of finding the nearest school to each node, then matching the buildings with nodes. I'm still not sure what would be the best way of connecting the building to a node.

One (awkward) way of doing so would be to also run the nearest_pois but with category = buildings, then joining the two two dataframes by node, and removing duplicate buildings. But this seems overly cumbersome.

@fillipefeitosa
Copy link
Contributor

@majdal

Hey friend, I got a similar problem and solved using OSMnx to get the "real distances" based on the street network and got the nearest using KDtree.

I had to find the nearest schools to a set of polygons centroids. To understand better check this notebook maps .

basically the algorithm will stretch the graph of the urban network.

nA = np.array(list(zip(polygon.geometry.x, polygon.geometry.y)) )
nB = np.array(list(zip(schools_preEscolar.geometry.x, schools_preEscolar.geometry.y)) )
btree = cKDTree(nB)
dist, idx = btree.query(nA, k=1)
polygon['place'] = idx
polygon['dist'] = dist

@CWen001
Copy link

CWen001 commented Jun 16, 2021

Hello. Is this feature on a development roadmap, please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants