{"id":1031,"date":"2026-10-18T14:33:17","date_gmt":"2026-10-18T14:33:17","guid":{"rendered":"https:\/\/helpwithmygisassignment.com\/blog\/?p=1031"},"modified":"2026-10-18T14:33:17","modified_gmt":"2026-10-18T14:33:17","slug":"how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely","status":"publish","type":"post","link":"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/","title":{"rendered":"How to Calculate Spatial Distance Matrices with Python SciPy and Shapely"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_89 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#How_to_Calculate_Spatial_Distance_Matrices_with_Python_SciPy_and_Shapely\" >How to Calculate Spatial Distance Matrices with Python SciPy and Shapely<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#1_Introduction_How_to_Calculate_Spatial_Distance_Matrices_with_Python_SciPy_and_Shapely\" >1. Introduction: How to Calculate Spatial Distance Matrices with Python SciPy and Shapely<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Why_are_distance_matrices_useful\" >Why are distance matrices useful?<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#2_Setup_and_Required_Libraries\" >2. Setup and Required Libraries<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#GeoPandas\" >GeoPandas<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Shapely\" >Shapely<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#SciPy\" >SciPy<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#3_Example_Dataset\" >3. Example Dataset<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Origins\" >Origins<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Destinations\" >Destinations<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#4_Step_1_%E2%80%94_Load_the_Point_Datasets\" >4. Step 1 \u2014 Load the Point Datasets<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#5_Step_2_%E2%80%94_Project_the_Data_to_a_CRS_Using_Meters\" >5. Step 2 \u2014 Project the Data to a CRS Using Meters<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Do_not_calculate_Euclidean_distance_directly_from_latitudelongitude\" >Do not calculate Euclidean distance directly from latitude\/longitude.<\/a><\/li><\/ul><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#6_Why_the_CRS_Matters\" >6. Why the CRS Matters<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#7_Step_3_%E2%80%94_Extract_X_and_Y_Coordinates\" >7. Step 3 \u2014 Extract X and Y Coordinates<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#8_Step_4_%E2%80%94_Convert_Coordinates_into_Arrays\" >8. Step 4 \u2014 Convert Coordinates into Arrays<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#9_Step_5_%E2%80%94_Calculate_the_Spatial_Distance_Matrix\" >9. Step 5 \u2014 Calculate the Spatial Distance Matrix<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#10_Understanding_cdist\" >10. Understanding cdist()<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#11_Inspect_the_Distance_Matrix\" >11. Inspect the Distance Matrix<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#12_Step_6_%E2%80%94_Find_the_Nearest_Destination\" >12. Step 6 \u2014 Find the Nearest Destination<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#13_Extract_the_Minimum_Distance\" >13. Extract the Minimum Distance<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#14_Step_7_%E2%80%94_Match_the_Index_to_the_Facility_ID\" >14. Step 7 \u2014 Match the Index to the Facility ID<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#15_Step_8_%E2%80%94_Create_a_Results_Table\" >15. Step 8 \u2014 Create a Results Table<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#16_Export_the_Nearest-Destination_Results\" >16. Export the Nearest-Destination Results<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#17_Export_the_Complete_Distance_Matrix\" >17. Export the Complete Distance Matrix<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#18_Complete_Workflow_Script\" >18. Complete Workflow Script<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#19_Performance_Considerations\" >19. Performance Considerations<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#20_Estimate_Matrix_Memory\" >20. Estimate Matrix Memory<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-29\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#21_When_You_Only_Need_the_Nearest_Neighbor\" >21. When You Only Need the Nearest Neighbor<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-30\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#22_Pairwise_Distance_Calculation_vs_Nearest_Neighbor\" >22. Pairwise Distance Calculation vs Nearest Neighbor<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-31\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#23_Important_Distance_Limitation\" >23. Important Distance Limitation<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-32\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#24_Conclusion\" >24. Conclusion<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-33\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/#Frequently_Asked_Questions\" >Frequently Asked Questions<\/a><\/li><\/ul><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"How_to_Calculate_Spatial_Distance_Matrices_with_Python_SciPy_and_Shapely\"><\/span>How to Calculate Spatial Distance Matrices with Python SciPy and Shapely<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p><b data-path-to-node=\"15,0\" data-index-in-node=\"1\">How to Calculate Spatial Distance Matrices with Python SciPy and Shapely<\/b> is essential for mastering spatial distance calculations in GIS workflows.\u00a0Whether you are determining which hospital is closest to a patient, matching warehouses to customers, or analyzing the nearest neighboring features, calculating distances between many points is a common requirement.<\/p>\n<p>Python provides an efficient combination of <a href=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-admin\/post.php?post=1031&amp;action=edit#\"><strong>GeoPandas<\/strong><\/a>, <strong>Shapely<\/strong>, and <a href=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-admin\/post.php?post=1031&amp;action=edit#\"><strong>SciPy<\/strong><\/a> for these workflows.<\/p>\n<p>This tutorial demonstrates how to build a <strong>Spatial Distance Matrix Python GeoPandas scipy<\/strong> workflow, calculate pairwise distances between two point datasets, identify the nearest destination for every origin, and export the results for further GIS or statistical analysis.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"1_Introduction_How_to_Calculate_Spatial_Distance_Matrices_with_Python_SciPy_and_Shapely\"><\/span>1. Introduction: How to Calculate Spatial Distance Matrices with Python SciPy and Shapely<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1233 size-large\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_jxgnksjxgnksjxgn-1024x559.jpg\" alt=\"Step-by-step visual guide on How to Calculate Spatial Distance Matrices with Python SciPy and Shapely showing customer origins and warehouse destinations.\" width=\"1024\" height=\"559\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_jxgnksjxgnksjxgn-1024x559.jpg 1024w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_jxgnksjxgnksjxgn-300x164.jpg 300w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_jxgnksjxgnksjxgn-768x419.jpg 768w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_jxgnksjxgnksjxgn.jpg 1408w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>A spatial distance matrix is a table or numerical array containing the distances between two or more sets of geographic features.<\/p>\n<p>Suppose you have:<\/p>\n<ul>\n<li>4 demand points representing customers<\/li>\n<li>3 destination points representing warehouses<\/li>\n<\/ul>\n<p>The resulting matrix could look like this:<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th><\/th>\n<th>Warehouse 1<\/th>\n<th>Warehouse 2<\/th>\n<th>Warehouse 3<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Customer 1<\/td>\n<td>2,150 m<\/td>\n<td>5,430 m<\/td>\n<td>3,210 m<\/td>\n<\/tr>\n<tr>\n<td>Customer 2<\/td>\n<td>1,870 m<\/td>\n<td>4,100 m<\/td>\n<td>2,950 m<\/td>\n<\/tr>\n<tr>\n<td>Customer 3<\/td>\n<td>6,210 m<\/td>\n<td>2,300 m<\/td>\n<td>1,540 m<\/td>\n<\/tr>\n<tr>\n<td>Customer 4<\/td>\n<td>3,450 m<\/td>\n<td>1,980 m<\/td>\n<td>4,220 m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p>Each row represents an <strong>origin<\/strong>, while each column represents a <strong>destination<\/strong>.<\/p>\n<p>Mathematically, if there are <code dir=\"ltr\">n<\/code> origins and <code dir=\"ltr\">m<\/code> destinations, the distance matrix has dimensions:<\/p>\n<p><span data-math-source=\"n \\times m\" data-math-display=\"true\">\\[ n \\times m \\]<\/span><\/p>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100 origins \u00d7 20 facilities<\/code><\/pre>\n<\/div>\n<p>produces:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100 \u00d7 20<\/code><\/pre>\n<\/div>\n<p>or <strong>2,000 individual distance calculations<\/strong>.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Why_are_distance_matrices_useful\"><\/span>Why are distance matrices useful?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Distance matrices are important in:<\/p>\n<ul>\n<li><strong>Facility location models<\/strong><\/li>\n<li>Supply-chain logistics<\/li>\n<li>Emergency-service planning<\/li>\n<li>Transportation analysis<\/li>\n<li>Nearest-neighbor analysis<\/li>\n<li>Customer-to-store allocation<\/li>\n<li>Healthcare accessibility studies<\/li>\n<li>School location analysis<\/li>\n<li>Spatial clustering<\/li>\n<li>Network planning<\/li>\n<\/ul>\n<p>A common question is:<\/p>\n<blockquote><p>&#8220;For every demand point, which facility is closest?&#8221;<\/p><\/blockquote>\n<p>A distance matrix gives you everything needed to answer that question.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"2_Setup_and_Required_Libraries\"><\/span>2. Setup and Required Libraries<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>We will use three primary geospatial\/scientific Python libraries:<\/p>\n<div>\n<pre dir=\"ltr\"><code>import geopandas as gpd\r\nfrom shapely.geometry import Point\r\nfrom scipy.spatial.distance import cdist<\/code><\/pre>\n<\/div>\n<p>Each library has a different role.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"GeoPandas\"><\/span>GeoPandas<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>GeoPandas handles spatial datasets and coordinate reference systems.<\/p>\n<div>\n<pre dir=\"ltr\"><code>import geopandas as gpd<\/code><\/pre>\n<\/div>\n<p>We will use it to:<\/p>\n<ul>\n<li>Read GIS files<\/li>\n<li>Manage GeoDataFrames<\/li>\n<li>Reproject coordinates<\/li>\n<li>Work with geometry columns<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"Shapely\"><\/span>Shapely<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Shapely provides geometric objects such as points, lines, and polygons.<\/p>\n<div>\n<pre dir=\"ltr\"><code>from shapely.geometry import Point<\/code><\/pre>\n<\/div>\n<p>In this tutorial, the geometries are already stored in our GeoDataFrames, so Shapely mainly provides the underlying geometry functionality.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"SciPy\"><\/span>SciPy<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>SciPy provides optimized scientific-computing algorithms.<\/p>\n<div>\n<pre dir=\"ltr\"><code>from scipy.spatial.distance import cdist<\/code><\/pre>\n<\/div>\n<div><\/div>\n<p><code dir=\"ltr\">cdist()<\/code> is particularly useful because it calculates the distances between <strong>every point in one dataset and every point in another dataset<\/strong>.<\/p>\n<p>Install the libraries if necessary:<\/p>\n<div>\n<pre dir=\"ltr\"><code>pip install geopandas shapely scipy<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"3_Example_Dataset\"><\/span>3. Example Dataset<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Imagine a logistics company with two spatial datasets:<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Origins\"><\/span>Origins<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>These represent customer demand locations.<\/p>\n<div>\n<pre dir=\"ltr\"><code>origins.gpkg<\/code><\/pre>\n<\/div>\n<p>Example attributes:<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th>Origin_ID<\/th>\n<th>Demand<\/th>\n<th>geometry<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>O001<\/td>\n<td>150<\/td>\n<td>Point<\/td>\n<\/tr>\n<tr>\n<td>O002<\/td>\n<td>320<\/td>\n<td>Point<\/td>\n<\/tr>\n<tr>\n<td>O003<\/td>\n<td>210<\/td>\n<td>Point<\/td>\n<\/tr>\n<tr>\n<td>O004<\/td>\n<td>450<\/td>\n<td>Point<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"Destinations\"><\/span>Destinations<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>These represent warehouses.<\/p>\n<div>\n<pre dir=\"ltr\"><code>facilities.gpkg<\/code><\/pre>\n<\/div>\n<p>Example attributes:<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th>Facility_ID<\/th>\n<th>Capacity<\/th>\n<th>geometry<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>F001<\/td>\n<td>5000<\/td>\n<td>Point<\/td>\n<\/tr>\n<tr>\n<td>F002<\/td>\n<td>3000<\/td>\n<td>Point<\/td>\n<\/tr>\n<tr>\n<td>F003<\/td>\n<td>7000<\/td>\n<td>Point<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p>Our goal is to calculate the distance from <strong>every origin to every facility<\/strong>.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"4_Step_1_%E2%80%94_Load_the_Point_Datasets\"><\/span>4. Step 1 \u2014 Load the Point Datasets<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Start by importing GeoPandas:<\/p>\n<div>\n<pre dir=\"ltr\"><code>import geopandas as gpd<\/code><\/pre>\n<\/div>\n<p>Read the two datasets:<\/p>\n<div>\n<pre dir=\"ltr\"><code>origins = gpd.read_file(\"origins.gpkg\")\r\nfacilities = gpd.read_file(\"facilities.gpkg\")<\/code><\/pre>\n<\/div>\n<p>Inspect them:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(origins.head())\r\nprint(facilities.head())<\/code><\/pre>\n<\/div>\n<p>You can also check their coordinate reference systems:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(\"Origins CRS:\", origins.crs)\r\nprint(\"Facilities CRS:\", facilities.crs)<\/code><\/pre>\n<\/div>\n<p>You might find:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origins CRS: EPSG:4326\r\nFacilities CRS: EPSG:4326<\/code><\/pre>\n<\/div>\n<p>This means the coordinates are stored as longitude and latitude.<\/p>\n<p>That creates an important problem.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"5_Step_2_%E2%80%94_Project_the_Data_to_a_CRS_Using_Meters\"><\/span>5. Step 2 \u2014 Project the Data to a CRS Using Meters<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<h3><span class=\"ez-toc-section\" id=\"Do_not_calculate_Euclidean_distance_directly_from_latitudelongitude\"><\/span>Do not calculate Euclidean distance directly from latitude\/longitude.<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Coordinates in:<\/p>\n<div>\n<pre dir=\"ltr\"><code>EPSG:4326<\/code><\/pre>\n<\/div>\n<p>are expressed in degrees.<\/p>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Longitude = 36.8172\r\nLatitude = -1.2864<\/code><\/pre>\n<\/div>\n<p>A difference of <code dir=\"ltr\">0.01<\/code> degrees does not represent a fixed distance in meters across the Earth&#8217;s surface.<\/p>\n<p>For Euclidean distance calculations, we therefore want a <strong>projected CRS whose units are meters<\/strong>.<\/p>\n<p>For a Kenyan study area, for example, you might use an appropriate UTM CRS for your area of interest.<\/p>\n<p>Suppose our data is in a suitable projected CRS:<\/p>\n<div>\n<pre dir=\"ltr\"><code>EPSG:32737<\/code><\/pre>\n<\/div>\n<p>You could reproject both datasets:<\/p>\n<div>\n<pre dir=\"ltr\"><code>origins_projected = origins.to_crs(\"EPSG:32737\")\r\nfacilities_projected = facilities.to_crs(\"EPSG:32737\")<\/code><\/pre>\n<\/div>\n<p>Now check the CRS:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(origins_projected.crs)<\/code><\/pre>\n<\/div>\n<p>The coordinates are now represented in meters.<\/p>\n<blockquote><p><strong>Important:<\/strong> The projected CRS should be appropriate for your study area. Do not blindly use one EPSG code for every project.<\/p><\/blockquote>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"6_Why_the_CRS_Matters\"><\/span>6. Why the CRS Matters<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Suppose two points have coordinates:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Point A: (500000, 9850000)\r\nPoint B: (501000, 9851000)<\/code><\/pre>\n<\/div>\n<p>Because the coordinates are in meters, we can calculate the Euclidean distance:<\/p>\n<p><span data-math-source=\"d = \\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2}\" data-math-display=\"true\">\\[ d = \\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2} \\]<\/span><\/p>\n<p>Therefore:<\/p>\n<p><span data-math-source=\"d = \\sqrt{1000^2 + 1000^2}\" data-math-display=\"true\">\\[ d = \\sqrt{1000^2 + 1000^2} \\]<\/span><\/p>\n<p>which gives approximately:<\/p>\n<div>\n<pre dir=\"ltr\"><code>1,414.21 meters<\/code><\/pre>\n<\/div>\n<p>This is exactly the type of calculation that <code dir=\"ltr\">scipy.spatial.distance.cdist()<\/code> performs efficiently.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"7_Step_3_%E2%80%94_Extract_X_and_Y_Coordinates\"><\/span>7. Step 3 \u2014 Extract X and Y Coordinates<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>SciPy does not directly calculate distances from GeoPandas geometry objects.<\/p>\n<p>We first extract the coordinates into numerical arrays.<\/p>\n<p>For the origins:<\/p>\n<div>\n<pre dir=\"ltr\"><code>origin_coords = [\r\n    [point.x, point.y]\r\n    for point in origins_projected.geometry\r\n]<\/code><\/pre>\n<\/div>\n<p>For the facilities:<\/p>\n<div>\n<pre dir=\"ltr\"><code>facility_coords = [\r\n    [point.x, point.y]\r\n    for point in facilities_projected.geometry\r\n]<\/code><\/pre>\n<\/div>\n<p>You can inspect the result:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(origin_coords[:3])\r\nprint(facility_coords[:3])<\/code><\/pre>\n<\/div>\n<p>You should see something similar to:<\/p>\n<div>\n<pre dir=\"ltr\"><code>[[500123.4, 9850123.7],\r\n [501230.8, 9851450.2],\r\n [498765.1, 9849320.6]]<\/code><\/pre>\n<\/div>\n<p>These are ordinary numerical coordinate pairs.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"8_Step_4_%E2%80%94_Convert_Coordinates_into_Arrays\"><\/span>8. Step 4 \u2014 Convert Coordinates into Arrays<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>For larger datasets,<a href=\"https:\/\/numpy.org\/\" target=\"_blank\" rel=\"noopener\"> NumPy<\/a> arrays are preferable.<\/p>\n<p>Import NumPy:<\/p>\n<div>\n<pre dir=\"ltr\"><code>import numpy as np<\/code><\/pre>\n<\/div>\n<p>Then:<\/p>\n<div>\n<pre dir=\"ltr\"><code>origin_coords = np.array([\r\n    [point.x, point.y]\r\n    for point in origins_projected.geometry\r\n])\r\n\r\nfacility_coords = np.array([\r\n    [point.x, point.y]\r\n    for point in facilities_projected.geometry\r\n])<\/code><\/pre>\n<\/div>\n<p>Now inspect their dimensions:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(origin_coords.shape)\r\nprint(facility_coords.shape)<\/code><\/pre>\n<\/div>\n<p>Suppose we have:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100 origins\r\n20 facilities<\/code><\/pre>\n<\/div>\n<p>The result would be:<\/p>\n<div>\n<pre dir=\"ltr\"><code>(100, 2)\r\n(20, 2)<\/code><\/pre>\n<\/div>\n<p>The <code dir=\"ltr\">2<\/code> represents:<\/p>\n<div>\n<pre dir=\"ltr\"><code>X coordinate\r\nY coordinate<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"9_Step_5_%E2%80%94_Calculate_the_Spatial_Distance_Matrix\"><\/span>9. Step 5 \u2014 Calculate the Spatial Distance Matrix<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-1234\" src=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_sl6ulusl6ulusl6u-1024x559.jpg\" alt=\"Python code snippet and output data table demonstrating How to Calculate Spatial Distance Matrices with Python SciPy and Shapely.\" width=\"1024\" height=\"559\" srcset=\"https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_sl6ulusl6ulusl6u-1024x559.jpg 1024w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_sl6ulusl6ulusl6u-300x164.jpg 300w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_sl6ulusl6ulusl6u-768x419.jpg 768w, https:\/\/helpwithmygisassignment.com\/blog\/wp-content\/uploads\/2026\/10\/Gemini_Generated_Image_sl6ulusl6ulusl6u.jpg 1408w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/p>\n<p>Now we can use SciPy&#8217;s <code dir=\"ltr\">cdist()<\/code>.<\/p>\n<div>\n<pre dir=\"ltr\"><code>from scipy.spatial.distance import cdist<\/code><\/pre>\n<\/div>\n<p>Calculate the distances:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_matrix = cdist(\r\n    origin_coords,\r\n    facility_coords,\r\n    metric=\"euclidean\"\r\n)<\/code><\/pre>\n<\/div>\n<p>This single operation calculates every origin-to-facility distance.<\/p>\n<p>If there are:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100 origins\r\n20 facilities<\/code><\/pre>\n<\/div>\n<p>the resulting matrix has:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100 rows \u00d7 20 columns<\/code><\/pre>\n<\/div>\n<p>Check its shape:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(distance_matrix.shape)<\/code><\/pre>\n<\/div>\n<div><\/div>\n<p>Output:<\/p>\n<div>\n<pre dir=\"ltr\"><code>(100, 20)<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"10_Understanding_cdist\"><\/span>10. Understanding <code dir=\"ltr\">cdist()<\/code><span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>The basic syntax is:<\/p>\n<div>\n<pre dir=\"ltr\"><code>cdist(A, B, metric=\"euclidean\")<\/code><\/pre>\n<\/div>\n<p>where:<\/p>\n<ul>\n<li><code dir=\"ltr\">A<\/code> = coordinates of the first dataset<\/li>\n<li><code dir=\"ltr\">B<\/code> = coordinates of the second dataset<\/li>\n<li><code dir=\"ltr\">metric<\/code> = distance calculation method<\/li>\n<\/ul>\n<p>In our case:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_matrix = cdist(\r\n    origin_coords,\r\n    facility_coords,\r\n    metric=\"euclidean\"\r\n)<\/code><\/pre>\n<\/div>\n<p>Conceptually, SciPy calculates:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origin 1 \u2192 Facility 1\r\nOrigin 1 \u2192 Facility 2\r\nOrigin 1 \u2192 Facility 3\r\n\r\nOrigin 2 \u2192 Facility 1\r\nOrigin 2 \u2192 Facility 2\r\nOrigin 2 \u2192 Facility 3\r\n\r\n...<\/code><\/pre>\n<\/div>\n<p>until every combination has been calculated.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"11_Inspect_the_Distance_Matrix\"><\/span>11. Inspect the Distance Matrix<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>You can print the matrix:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(distance_matrix)<\/code><\/pre>\n<\/div>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>[[2150.4 5430.7 3210.2]\r\n [1870.5 4100.1 2950.6]\r\n [6210.8 2300.4 1540.7]\r\n [3450.2 1980.6 4220.3]]<\/code><\/pre>\n<\/div>\n<p>The first row corresponds to the first origin.<\/p>\n<p>The columns correspond to the facilities.<\/p>\n<p>Therefore:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_matrix[0, 0]<\/code><\/pre>\n<\/div>\n<p>means:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origin 1 \u2192 Facility 1<\/code><\/pre>\n<\/div>\n<p>while:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_matrix[0, 1]<\/code><\/pre>\n<\/div>\n<p>means:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origin 1 \u2192 Facility 2<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"12_Step_6_%E2%80%94_Find_the_Nearest_Destination\"><\/span>12. Step 6 \u2014 Find the Nearest Destination<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>A common requirement is not the entire matrix but simply the closest destination for every origin.<\/p>\n<p>NumPy&#8217;s <code dir=\"ltr\">argmin()<\/code> is useful here.<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_indices = np.argmin(\r\n    distance_matrix,\r\n    axis=1\r\n)<\/code><\/pre>\n<\/div>\n<p>Why <code dir=\"ltr\">axis=1<\/code>?<\/p>\n<p>Each row represents one origin.<\/p>\n<p>We want to find the minimum value <strong>within each row<\/strong>.<\/p>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origin 1:\r\n[2150, 5430, 3210]<\/code><\/pre>\n<\/div>\n<p>The smallest value is:<\/p>\n<div>\n<pre dir=\"ltr\"><code>2150<\/code><\/pre>\n<\/div>\n<p>and its column index is:<\/p>\n<div>\n<pre dir=\"ltr\"><code>0<\/code><\/pre>\n<\/div>\n<p>Therefore, Facility 1 is the nearest facility.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"13_Extract_the_Minimum_Distance\"><\/span>13. Extract the Minimum Distance<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>We can obtain the actual minimum distance using:<\/p>\n<div>\n<pre dir=\"ltr\"><code>minimum_distances = np.min(\r\n    distance_matrix,\r\n    axis=1\r\n)<\/code><\/pre>\n<\/div>\n<p>Now we have two arrays:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_indices\r\nminimum_distances<\/code><\/pre>\n<\/div>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_indices:\r\n[0, 0, 2, 1]\r\n\r\nminimum_distances:\r\n[2150.4, 1870.5, 1540.7, 1980.6]<\/code><\/pre>\n<\/div>\n<p>This tells us which facility is nearest and how far away it is.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"14_Step_7_%E2%80%94_Match_the_Index_to_the_Facility_ID\"><\/span>14. Step 7 \u2014 Match the Index to the Facility ID<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>The <code dir=\"ltr\">argmin()<\/code> result gives us a <strong>position<\/strong>, not necessarily the actual facility ID.<\/p>\n<p>Suppose:<\/p>\n<div>\n<pre dir=\"ltr\"><code>facilities_projected[\"Facility_ID\"]<\/code><\/pre>\n<\/div>\n<p>contains:<\/p>\n<div>\n<pre dir=\"ltr\"><code>F001\r\nF002\r\nF003<\/code><\/pre>\n<\/div>\n<p>We can use the indices:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_facilities = facilities_projected.iloc[\r\n    nearest_indices\r\n][\"Facility_ID\"].values<\/code><\/pre>\n<\/div>\n<p>Now:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_indices<\/code><\/pre>\n<\/div>\n<p>might be:<\/p>\n<div>\n<pre dir=\"ltr\"><code>[0, 0, 2, 1]<\/code><\/pre>\n<\/div>\n<p>while:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_facilities<\/code><\/pre>\n<\/div>\n<p>becomes:<\/p>\n<div>\n<pre dir=\"ltr\"><code>[\"F001\", \"F001\", \"F003\", \"F002\"]<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"15_Step_8_%E2%80%94_Create_a_Results_Table\"><\/span>15. Step 8 \u2014 Create a Results Table<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>We can now construct a pandas DataFrame.<\/p>\n<div>\n<pre dir=\"ltr\"><code>import pandas as pd\r\n\r\nresults = pd.DataFrame({\r\n    \"Origin_ID\": origins_projected[\"Origin_ID\"].values,\r\n    \"Nearest_Facility\": nearest_facilities,\r\n    \"Distance_m\": minimum_distances\r\n})<\/code><\/pre>\n<\/div>\n<p>Inspect the result:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(results.head())<\/code><\/pre>\n<\/div>\n<p>You might get:<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th>Origin_ID<\/th>\n<th>Nearest_Facility<\/th>\n<th>Distance_m<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>O001<\/td>\n<td>F001<\/td>\n<td>2150.4<\/td>\n<\/tr>\n<tr>\n<td>O002<\/td>\n<td>F001<\/td>\n<td>1870.5<\/td>\n<\/tr>\n<tr>\n<td>O003<\/td>\n<td>F003<\/td>\n<td>1540.7<\/td>\n<\/tr>\n<tr>\n<td>O004<\/td>\n<td>F002<\/td>\n<td>1980.6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p>This table can now be used for statistical analysis, reporting, or GIS visualization.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"16_Export_the_Nearest-Destination_Results\"><\/span>16. Export the Nearest-Destination Results<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Save the table as CSV:<\/p>\n<div>\n<pre dir=\"ltr\"><code>results.to_csv(\r\n    \"nearest_facilities.csv\",\r\n    index=False\r\n)<\/code><\/pre>\n<\/div>\n<p>The resulting file might look like:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Origin_ID,Nearest_Facility,Distance_m\r\nO001,F001,2150.4\r\nO002,F001,1870.5\r\nO003,F003,1540.7\r\nO004,F002,1980.6<\/code><\/pre>\n<\/div>\n<p>You can open this in Excel, QGIS, ArcGIS Pro, pandas, or another analytical system.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"17_Export_the_Complete_Distance_Matrix\"><\/span>17. Export the Complete Distance Matrix<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Sometimes you need <strong>every origin-to-destination distance<\/strong>, not just the nearest facility.<\/p>\n<p>One convenient approach is to use the destination IDs as column names.<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_df = pd.DataFrame(\r\n    distance_matrix,\r\n    index=origins_projected[\"Origin_ID\"],\r\n    columns=facilities_projected[\"Facility_ID\"]\r\n)<\/code><\/pre>\n<\/div>\n<p>Inspect it:<\/p>\n<div>\n<pre dir=\"ltr\"><code>print(distance_df.head())<\/code><\/pre>\n<\/div>\n<p>The result might look like:<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th>Origin_ID<\/th>\n<th>F001<\/th>\n<th>F002<\/th>\n<th>F003<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>O001<\/td>\n<td>2150<\/td>\n<td>5431<\/td>\n<td>3210<\/td>\n<\/tr>\n<tr>\n<td>O002<\/td>\n<td>1871<\/td>\n<td>4100<\/td>\n<td>2951<\/td>\n<\/tr>\n<tr>\n<td>O003<\/td>\n<td>6211<\/td>\n<td>2300<\/td>\n<td>1541<\/td>\n<\/tr>\n<tr>\n<td>O004<\/td>\n<td>3450<\/td>\n<td>1981<\/td>\n<td>4220<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p>Export it:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_df.to_csv(\r\n    \"spatial_distance_matrix.csv\"\r\n)<\/code><\/pre>\n<\/div>\n<p>You now have a complete <strong>Spatial Distance Matrix Python GeoPandas scipy<\/strong> output.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"18_Complete_Workflow_Script\"><\/span>18. Complete Workflow Script<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>Here is the complete workflow assembled into one script:<\/p>\n<div>\n<pre dir=\"ltr\"><code>import geopandas as gpd\r\nimport pandas as pd\r\nimport numpy as np\r\nfrom scipy.spatial.distance import cdist\r\n\r\n\r\n# --------------------------------------------------\r\n# 1. Load datasets\r\n# --------------------------------------------------\r\n\r\norigins = gpd.read_file(\"origins.gpkg\")\r\nfacilities = gpd.read_file(\"facilities.gpkg\")\r\n\r\n\r\n# --------------------------------------------------\r\n# 2. Project both datasets to a CRS in meters\r\n# --------------------------------------------------\r\n\r\ntarget_crs = \"EPSG:32737\"\r\n\r\norigins_projected = origins.to_crs(target_crs)\r\nfacilities_projected = facilities.to_crs(target_crs)\r\n\r\n\r\n# --------------------------------------------------\r\n# 3. Extract X\/Y coordinates\r\n# --------------------------------------------------\r\n\r\norigin_coords = np.array([\r\n    [point.x, point.y]\r\n    for point in origins_projected.geometry\r\n])\r\n\r\nfacility_coords = np.array([\r\n    [point.x, point.y]\r\n    for point in facilities_projected.geometry\r\n])\r\n\r\n\r\n# --------------------------------------------------\r\n# 4. Calculate pairwise distances\r\n# --------------------------------------------------\r\n\r\ndistance_matrix = cdist(\r\n    origin_coords,\r\n    facility_coords,\r\n    metric=\"euclidean\"\r\n)\r\n\r\n\r\n# --------------------------------------------------\r\n# 5. Find nearest facility for each origin\r\n# --------------------------------------------------\r\n\r\nnearest_indices = np.argmin(\r\n    distance_matrix,\r\n    axis=1\r\n)\r\n\r\nminimum_distances = np.min(\r\n    distance_matrix,\r\n    axis=1\r\n)\r\n\r\n\r\n# --------------------------------------------------\r\n# 6. Convert facility indices to IDs\r\n# --------------------------------------------------\r\n\r\nnearest_facilities = facilities_projected.iloc[\r\n    nearest_indices\r\n][\"Facility_ID\"].values\r\n\r\n\r\n# --------------------------------------------------\r\n# 7. Create nearest-facility results\r\n# --------------------------------------------------\r\n\r\nresults = pd.DataFrame({\r\n    \"Origin_ID\": origins_projected[\"Origin_ID\"].values,\r\n    \"Nearest_Facility\": nearest_facilities,\r\n    \"Distance_m\": minimum_distances\r\n})\r\n\r\n\r\n# --------------------------------------------------\r\n# 8. Save nearest-facility table\r\n# --------------------------------------------------\r\n\r\nresults.to_csv(\r\n    \"nearest_facilities.csv\",\r\n    index=False\r\n)\r\n\r\n\r\n# --------------------------------------------------\r\n# 9. Create complete distance matrix\r\n# --------------------------------------------------\r\n\r\ndistance_df = pd.DataFrame(\r\n    distance_matrix,\r\n    index=origins_projected[\"Origin_ID\"],\r\n    columns=facilities_projected[\"Facility_ID\"]\r\n)\r\n\r\n\r\n# --------------------------------------------------\r\n# 10. Save complete matrix\r\n# --------------------------------------------------\r\n\r\ndistance_df.to_csv(\r\n    \"spatial_distance_matrix.csv\"\r\n)\r\n\r\n\r\n# --------------------------------------------------\r\n# 11. Print summary\r\n# --------------------------------------------------\r\n\r\nprint(\"Distance calculation completed.\")\r\nprint(f\"Origins: {len(origins_projected)}\")\r\nprint(f\"Facilities: {len(facilities_projected)}\")\r\nprint(f\"Matrix shape: {distance_matrix.shape}\")<\/code><\/pre>\n<\/div>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"19_Performance_Considerations\"><\/span>19. Performance Considerations<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>The main limitation of a full distance matrix is <strong>size<\/strong>.<\/p>\n<p>If you have:<\/p>\n<div>\n<pre dir=\"ltr\"><code>1,000 origins\r\n500 facilities<\/code><\/pre>\n<\/div>\n<p>you need:<\/p>\n<p><span data-math-source=\"1,000 \\times 500 = 500,000\" data-math-display=\"true\">\\[ 1,000 \\times 500 = 500,000 \\]<\/span><\/p>\n<p>distance calculations.<\/p>\n<p>That is manageable.<\/p>\n<p>But consider:<\/p>\n<div>\n<pre dir=\"ltr\"><code>100,000 origins\r\n50,000 facilities<\/code><\/pre>\n<\/div>\n<p>The matrix would contain:<\/p>\n<p><span data-math-source=\"100,000 \\times 50,000 = 5,000,000,000\" data-math-display=\"true\">\\[ 100,000 \\times 50,000 = 5,000,000,000 \\]<\/span><\/p>\n<p>distance values.<\/p>\n<p>That is <strong>5 billion values<\/strong>, which can require enormous amounts of memory.<\/p>\n<p>Therefore, you should not automatically create a full matrix for very large datasets.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"20_Estimate_Matrix_Memory\"><\/span>20. Estimate Matrix Memory<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>A NumPy <code dir=\"ltr\">float64<\/code> value requires approximately 8 bytes.<\/p>\n<p>You can estimate memory requirements:<\/p>\n<div>\n<pre dir=\"ltr\"><code>n_origins = len(origins_projected)\r\nn_facilities = len(facilities_projected)\r\n\r\nmemory_bytes = (\r\n    n_origins *\r\n    n_facilities *\r\n    8\r\n)\r\n\r\nmemory_gb = memory_bytes \/ (1024 ** 3)\r\n\r\nprint(\r\n    f\"Estimated matrix size: \"\r\n    f\"{memory_gb:.2f} GB\"\r\n)<\/code><\/pre>\n<\/div>\n<p>This is a useful check before running <code dir=\"ltr\">cdist()<\/code> on a large dataset.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"21_When_You_Only_Need_the_Nearest_Neighbor\"><\/span>21. When You Only Need the Nearest Neighbor<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>If your actual question is:<\/p>\n<blockquote><p>&#8220;Which facility is closest to each origin?&#8221;<\/p><\/blockquote>\n<p>you may not need to generate every possible origin-to-facility distance.<\/p>\n<p>GeoPandas provides spatial nearest-neighbor functionality that can be more appropriate for this type of problem.<\/p>\n<p>For example:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest = gpd.sjoin_nearest(\r\n    origins_projected,\r\n    facilities_projected,\r\n    how=\"left\",\r\n    distance_col=\"Distance_m\"\r\n)<\/code><\/pre>\n<\/div>\n<p>This directly performs a nearest spatial join.<\/p>\n<p>For very large datasets, this type of spatial-index-based approach can be substantially more appropriate than constructing a massive dense distance matrix.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"22_Pairwise_Distance_Calculation_vs_Nearest_Neighbor\"><\/span>22. Pairwise Distance Calculation vs Nearest Neighbor<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>These approaches answer slightly different questions.<\/p>\n<div>\n<div>\n<div>\n<table>\n<thead>\n<tr>\n<th>Task<\/th>\n<th>Suitable approach<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Every origin-to-every-facility distance<\/td>\n<td><code dir=\"ltr\">scipy.spatial.distance.cdist()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Find nearest facility<\/td>\n<td><code dir=\"ltr\">gpd.sjoin_nearest()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Calculate all distances for a small dataset<\/td>\n<td><code dir=\"ltr\">cdist()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Very large nearest-neighbor problem<\/td>\n<td>Spatial index \/ nearest join<\/td>\n<\/tr>\n<tr>\n<td>Statistical distance analysis<\/td>\n<td>Distance matrix<\/td>\n<\/tr>\n<tr>\n<td>Facility allocation modeling<\/td>\n<td>Distance matrix or optimized nearest search<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p>The key is to choose the algorithm based on the analytical question rather than automatically generating the largest possible matrix.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"23_Important_Distance_Limitation\"><\/span>23. Important Distance Limitation<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>The <code dir=\"ltr\">cdist()<\/code> workflow calculates <strong>Euclidean distance between projected coordinates<\/strong>.<\/p>\n<p>That means:<\/p>\n<div>\n<pre dir=\"ltr\"><code>straight-line distance<\/code><\/pre>\n<\/div>\n<p>It does <strong>not<\/strong> calculate:<\/p>\n<div>\n<pre dir=\"ltr\"><code>road distance\r\ndriving distance\r\ntravel time\r\nwalking distance<\/code><\/pre>\n<\/div>\n<p>For example, two locations might be 2 km apart in Euclidean space but 5 km apart by road because of rivers, highways, restricted areas, or the street network.<\/p>\n<p>Therefore:<\/p>\n<blockquote><p>Use <code dir=\"ltr\">cdist()<\/code> when straight-line distance is appropriate to your analysis.<\/p><\/blockquote>\n<p>For transportation and logistics applications where actual travel distance matters, a <strong>network analysis<\/strong> workflow is usually more appropriate.<\/p>\n<hr \/>\n<h1><span class=\"ez-toc-section\" id=\"24_Conclusion\"><\/span>24. Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<p>A spatial distance matrix provides a structured way to quantify the relationship between locations.<\/p>\n<p>Using <strong>GeoPandas, Shapely, NumPy, and SciPy<\/strong>, the basic workflow is:<\/p>\n<div>\n<pre dir=\"ltr\"><code>Load spatial datasets\r\n        \u2193\r\nProject to a suitable CRS\r\n        \u2193\r\nExtract X\/Y coordinates\r\n        \u2193\r\nCreate coordinate arrays\r\n        \u2193\r\nCalculate pairwise distances\r\n        \u2193\r\nFind minimum distances\r\n        \u2193\r\nMatch nearest destination IDs\r\n        \u2193\r\nExport results<\/code><\/pre>\n<\/div>\n<p>The core calculation is remarkably compact:<\/p>\n<div>\n<pre dir=\"ltr\"><code>distance_matrix = cdist(\r\n    origin_coords,\r\n    facility_coords,\r\n    metric=\"euclidean\"\r\n)<\/code><\/pre>\n<\/div>\n<p>And finding the nearest destination for each origin requires only:<\/p>\n<div>\n<pre dir=\"ltr\"><code>nearest_indices = np.argmin(    distance_matrix,    axis=1)minimum_distances = np.min(    distance_matrix,    axis=1)<\/code><\/pre>\n<\/div>\n<div><\/div>\n<p>The most important considerations are <strong>CRS selection, coordinate order, matrix size, and choosing Euclidean distance versus network distance<\/strong>.<\/p>\n<p>Once you understand this workflow, you can extend it to facility location models, supply-chain optimization, accessibility analysis, and <strong>nearest neighbor analysis in Python<\/strong> without manually calculating individual GIS distances.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Frequently_Asked_Questions\"><\/span>Frequently Asked Questions<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><strong>What tools are required for How to Calculate Spatial Distance Matrices with Python SciPy and Shapely?<\/strong><br \/>\nTo run this workflow, you need GeoPandas for reading and managing spatial files, Shapely for geometry handling, NumPy for array structuring, and SciPy&#8217;s `cdist` function for high-speed pairwise calculations.<\/p>\n<p><strong>Why is data projection important when learning How to Calculate Spatial Distance Matrices with Python SciPy and Shapely?<\/strong><br \/>\nUnprojected latitude and longitude coordinates (like EPSG:4326) measure positions in degrees, which do not translate to uniform meter distances. Reprojecting your origins and facilities to a local metric CRS (such as UTM) ensures your Euclidean distance matrix is accurate.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to Calculate Spatial Distance Matrices with Python SciPy and Shapely How to Calculate Spatial Distance Matrices with Python SciPy and Shapely is essential for mastering spatial distance calculations in GIS workflows.\u00a0Whether you are determining which hospital is closest to a patient, matching warehouses to customers, or analyzing the nearest neighboring features, calculating distances between &#8230; <a title=\"How to Calculate Spatial Distance Matrices with Python SciPy and Shapely\" class=\"read-more\" href=\"https:\/\/helpwithmygisassignment.com\/blog\/how-to-calculate-spatial-distance-matrices-with-python-scipy-and-shapely\/\" aria-label=\"Read more about How to Calculate Spatial Distance Matrices with Python SciPy and Shapely\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":1233,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,5,4],"tags":[],"class_list":["post-1031","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-civil-engineering","category-general-articles","category-gis-articles"],"_links":{"self":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/comments?post=1031"}],"version-history":[{"count":3,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1031\/revisions"}],"predecessor-version":[{"id":1235,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/posts\/1031\/revisions\/1235"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/media\/1233"}],"wp:attachment":[{"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/media?parent=1031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/categories?post=1031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helpwithmygisassignment.com\/blog\/wp-json\/wp\/v2\/tags?post=1031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}