<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Spatial Analysis Archives - Urban Geo Analytics</title>
	<atom:link href="https://urbangeoanalytics.com/tag/spatial-analysis/feed/" rel="self" type="application/rss+xml" />
	<link>https://urbangeoanalytics.com/tag/spatial-analysis/</link>
	<description>Spatial Analysis, GeoAI &#38; Machine Learning</description>
	<lastBuildDate>Wed, 17 Dec 2025 17:07:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://urbangeoanalytics.com/wp-content/uploads/2025/11/cropped-logo-urban-geo_512-32x32.png</url>
	<title>Spatial Analysis Archives - Urban Geo Analytics</title>
	<link>https://urbangeoanalytics.com/tag/spatial-analysis/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>A Stable and Reproducible Vision–Language Inference Engine for SAGAI v1.1</title>
		<link>https://urbangeoanalytics.com/a-stable-and-reproducible-vision-language-inference-engine-for-sagai-v1-1/</link>
					<comments>https://urbangeoanalytics.com/a-stable-and-reproducible-vision-language-inference-engine-for-sagai-v1-1/#respond</comments>
		
		<dc:creator><![CDATA[Joan Perez]]></dc:creator>
		<pubDate>Wed, 17 Dec 2025 17:03:56 +0000</pubDate>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Urbanism]]></category>
		<category><![CDATA[Vision Language Model]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Cloud Computing]]></category>
		<category><![CDATA[GIS]]></category>
		<category><![CDATA[Llava]]></category>
		<category><![CDATA[Spatial Analysis]]></category>
		<guid isPermaLink="false">https://urbangeoanalytics.com/?p=2275</guid>

					<description><![CDATA[<p>SAGAI v1.1 introduces Module 3 v2.0, a stable and reproducible vision–language inference engine for streetscape analysis. Built exclusively on Hugging Face LLaVA models, it enables robust multimodal processing of street-level images for large-scale urban and geospatial analysis.</p>
<p>The post <a href="https://urbangeoanalytics.com/a-stable-and-reproducible-vision-language-inference-engine-for-sagai-v1-1/">A Stable and Reproducible Vision–Language Inference Engine for SAGAI v1.1</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box fusion-builder-row-1 fusion-flex-container has-pattern-background has-mask-background nonhundred-percent-fullwidth non-hundred-percent-height-scrolling" style="--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;" id="contenu" ><div class="fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap" style="max-width:1248px;margin-left: calc(-4% / 2 );margin-right: calc(-4% / 2 );"><div class="fusion-layout-column fusion_builder_column fusion-builder-column-0 fusion_builder_column_3_4 3_4 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:75%;--awb-margin-top-large:0px;--awb-spacing-right-large:2.56%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:2.56%;--awb-width-medium:75%;--awb-order-medium:0;--awb-spacing-right-medium:2.56%;--awb-spacing-left-medium:2.56%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" id="contenu" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-image-element " style="--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-1 hover-type-none"><img fetchpriority="high" decoding="async" width="1536" height="1024" title="Sagai 1.1" src="https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1.png" alt class="img-responsive wp-image-2278" srcset="https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1-200x133.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1-400x267.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1-600x400.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1-800x533.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1-1200x800.png 1200w, https://urbangeoanalytics.com/wp-content/uploads/2025/12/Sagai-1.1.png 1536w" sizes="(max-width: 640px) 100vw, 1200px" /></span></div><div class="fusion-text fusion-text-1"><h5><strong>Highlights</strong></h5>
</div><div class="fusion-text fusion-text-2" style="--awb-margin-top:-30px;"><ul>
<li><strong data-start="142" data-end="159">Module 3 v2.0</strong> is the refactored inference engine of <strong data-start="198" data-end="212" data-is-only-node="">SAGAI v1.1</strong>, designed for stable and reproducible vision–language analysis of streetscape images</li>
<li>The new architecture relies <strong data-start="329" data-end="389">exclusively on Hugging Face–native LLaVA models and APIs</strong>, removing dependencies on research codebases.</li>
<li>Multimodal prompting, image–text alignment, and inference are handled through <strong data-start="516" data-end="555">standardized Transformers workflows</strong>, ensuring long-term compatibility.</li>
</ul>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-1 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);">Introduction</h2></div><div class="fusion-text fusion-text-3 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p data-start="438" data-end="784">Module 3 is the inference core of the <strong data-start="476" data-end="548">SAGAI (Streetscape Analysis with Generative Artificial Intelligence)</strong> framework. Its role is to transform large collections of street-level images into <strong data-start="631" data-end="667">structured, quantitative outputs</strong> using vision–language models (VLMs), enabling systematic streetscape analysis and subsequent geospatial aggregation.</p>
<p data-start="786" data-end="1114">With <strong data-start="791" data-end="805">SAGAI v1.1</strong>, Module 3 has been released in a new major version (<strong data-start="858" data-end="875">Module 3 v2.0</strong>) that introduces a fully standardized and maintenance-safe inference architecture. This update reflects both the maturation of multimodal model ecosystems and the need for long-term reproducibility in large-scale urban analysis pipelines.</p>
<p data-start="1116" data-end="1480">Earlier iterations of Module 3 were developed during a period of rapid evolution in both LLaVA research codebases and execution environments such as Google Colab. As multimodal models transitioned toward <strong data-start="1320" data-end="1388">Transformers-native implementations distributed via Hugging Face</strong>, assumptions embedded in earlier hybrid workflows became increasingly difficult to sustain.</p>
<p data-start="1482" data-end="1811">Module 3 v2.0 addresses this evolution by aligning the entire inference pipeline with <strong data-start="1568" data-end="1609">official Hugging Face multimodal APIs</strong>. Model loading, prompt formatting, image–text fusion, and generation are now handled through maintained and versioned components, ensuring compatibility across environments, models, and future updates.</p>
<p data-start="1813" data-end="2040">This document details the architectural context motivating the update, the design choices behind the refactored inference engine, and the rationale for releasing Module 3 v2.0 as a long-term, stable component of <strong data-start="2025" data-end="2039">SAGAI v1.1</strong>.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-2 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);">1. Architectural Context of Module 3 in the Previous version: SAGAI v1.0</h2></div><div class="fusion-text fusion-text-4 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The initial implementation of Module 3 (SAGAI v1.0) relied on a <strong data-start="280" data-end="353">hybrid architecture that mixed two incompatible sources of LLaVA code</strong>, combined with a rapidly evolving execution environment in Google Colab. This design choice made the pipeline fragile and ultimately unsustainable.</p>
<p data-start="503" data-end="1003">First, the pipeline simultaneously depended on the <strong data-start="554" data-end="581">LLaVA GitHub repository</strong> (<code data-start="583" data-end="602"><span style="font-size: 10.0pt;">haotian-liu/LLaVA</span></code>) and on <strong data-start="611" data-end="652">Hugging Face–hosted model checkpoints</strong>. The GitHub repository is a research-oriented codebase under active development. Its internal APIs, class structures, and utilities evolve rapidly and are not version-locked. Constructors, module paths, and helper functions may change or disappear without notice, and the repository is not designed to maintain backward compatibility across releases.</p>
<p data-start="1005" data-end="1528">At the same time, pretrained model weights were downloaded from Hugging Face. These checkpoints follow the <strong data-start="1112" data-end="1153">Transformers-native multimodal format</strong>, using Hugging Face–specific configuration files, processors, and model classes (e.g., <code data-start="1241" data-end="1276"><span style="font-size: 10.0pt;">LlavaNextForConditionalGeneration</span></code>, <code data-start="1278" data-end="1293"><span style="font-size: 10.0pt;">AutoProcessor</span></code>, and chat templates). This architecture is fundamentally different from the internal design assumed by the GitHub LLaVA code, which relies on custom token insertion, internal vision tower management, and non-Transformers abstractions.</p>
<p data-start="1530" data-end="1846">As a result, the pipeline operated in a <strong data-start="1570" data-end="1593">structural mismatch</strong>: GitHub code expected architectural fields, model attributes, and tokenizer behavior that were not present in Hugging Face checkpoints, while Hugging Face checkpoints expected model wrappers and configuration logic that the GitHub code did not provide.</p>
<p data-start="1848" data-end="2245">This fragility was exposed when <strong data-start="1880" data-end="1929">Google Colab upgraded its backend environment</strong> in early 2025. Major changes included Python 3.12, NumPy ≥ 2.0 (introducing ABI-breaking changes for compiled extensions), newer PyTorch releases (≥ 2.2), and updated system libraries. These updates caused widespread failures in binary dependencies and research codebases that were not aligned with the new runtime.</p>
<p data-start="2247" data-end="2577">In practice, this led to errors such as NumPy ABI incompatibilities, PyTorch extension failures, missing or renamed modules, and import errors in LLaVA GitHub utilities. Because the pipeline depended on both unstable research code and binary-sensitive extensions, even minor environment updates were sufficient to break execution.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-3 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);">2. Refactoring of the Inference Engine in SAGAI v1.1</h2></div><div class="fusion-text fusion-text-5 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p style="text-align: justify;">Module 3 has been fully refactored to <strong data-start="341" data-end="406">remove any dependency on the original LLaVA GitHub repository</strong>. The inference pipeline now relies exclusively on <strong data-start="457" data-end="502">Hugging Face–native LLaVA models and APIs</strong>, ensuring long-term stability and compatibility with evolving software environments.</p>
<p style="text-align: justify;" data-start="589" data-end="1175">In the previous architecture, the script depended on cloning the LLaVA GitHub repository, installing it in editable mode, and importing internal modules (<code data-start="743" data-end="752"><span style="font-size: 10.0pt;">llava.*</span></code>). Prompts were manually assembled using LLaVA-specific multimodal tokens (e.g., <code data-start="833" data-end="845"><span style="font-size: 10.0pt;">&lt;im_start&gt;</span></code>, <code data-start="847" data-end="856"><span style="font-size: 10.0pt;">&lt;image&gt;</span></code>), custom separators, and internal utilities. Image tokens and embeddings were explicitly inserted into the prompt, tightly coupling the forward pass to a specific implementation of the LLaVA codebase. As a result, updates to Google Colab, PyTorch, NumPy, or the LLaVA repository frequently introduced breaking changes.</p>
<p style="text-align: justify;" data-start="1177" data-end="1752">The current implementation removes all such dependencies. Prompt formatting and multimodal input construction are now handled entirely through Hugging Face abstractions. Prompts are formatted using <code data-start="1375" data-end="1408"><span style="font-size: 10.0pt;">processor.apply_chat_template()</span></code>, while images and text are combined using <code data-start="1451" data-end="1480"><span style="font-size: 10.0pt;">processor(images=…, text=…)</span></code>. Image embedding alignment, multimodal token placement, and chat formatting are fully managed by the Hugging Face processor and model configuration. Inference is performed using the standard <code data-start="1672" data-end="1690"><span style="font-size: 10.0pt;">model.generate()</span></code> API, without any custom token handling or internal utilities.</p>
<p style="text-align: justify;" data-start="1754" data-end="2177">This refactoring makes the SAGAI inference engine <strong data-start="1804" data-end="1862">model-agnostic within the Hugging Face LLaVA ecosystem</strong>. The same forward pass is compatible with LLaVA-NeXT (v1.6), LLaVA-Interleave, LLaVA-OneVision, and future Hugging Face LLaVA releases that expose a processor and chat template. Switching between models or architectures requires only changing the <code data-start="2110" data-end="2120"><span style="font-size: 10.0pt;">model_id</span></code>, with no modification to prompt logic or inference code.</p>
<p style="text-align: justify;" data-start="2179" data-end="2639">To ensure reliable downstream analysis, Module 3 also includes a dedicated <strong data-start="2254" data-end="2291">numeric output stabilization step</strong>. After decoding the model response, any prompt echoes or metadata—including residual <code data-start="2377" data-end="2395"><span style="font-size: 10.0pt;">[INST] … [/INST]</span></code> segments—are removed. The final output is parsed using a simple regular expression to retain only numeric values (e.g., <code data-start="2516" data-end="2519"><span style="font-size: 10.0pt;">0</span></code>, <code data-start="2521" data-end="2524"><span style="font-size: 10.0pt;">1</span></code>, <code data-start="2526" data-end="2529"><span style="font-size: 10.0pt;">2</span></code>, <code data-start="2531" data-end="2536"><span style="font-size: 10.0pt;">1.5</span></code>). This guarantees clean, machine-readable outputs and a stable CSV format across all supported models.</p>
<p style="text-align: justify;" data-start="2641" data-end="3230">Model loading has been simplified and standardized using Hugging Face–approved APIs. Both the processor and the model are instantiated directly from Hugging Face model cards via <code data-start="2819" data-end="2836"><span style="font-size: 10.0pt;">from_pretrained</span></code>, with optional 4-bit quantization enabled through <code data-start="2887" data-end="2906"><span style="font-size: 10.0pt;">load_in_4bit=True</span></code>. This eliminates the need for manual vision-tower initialization, deprecated classes, or custom C++ operators, and avoids common incompatibilities related to PyTorch, CUDA, or NumPy upgrades in Google Colab. Official Hugging Face code paths ensure that pretrained weights are always matched with the correct implementation.</p>
<p style="text-align: justify;" data-start="3232" data-end="3456">Optional authentication using a Hugging Face access token is supported to avoid rate limits and improve download reliability when working with large checkpoints, though public models remain accessible without authentication.</p>
<p style="text-align: justify;" data-start="3458" data-end="3697">Overall, this refactoring significantly improves <strong data-start="3507" data-end="3559">robustness, reproducibility, and maintainability</strong>, while enabling systematic experimentation across multiple LLaVA variants and quantization settings within a unified inference framework.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-4 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);">3. Rationale for a Long-Term, Stable Release</h2></div><div class="fusion-text fusion-text-6 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p style="text-align: justify;">The refactored inference system in Module 3 is designed as a <strong data-start="332" data-end="371">long-term, maintenance-safe release</strong>. This is achieved by aligning the entire pipeline with Hugging Face’s officially supported multimodal APIs and model distribution mechanisms.</p>
<p style="text-align: justify;" data-start="560" data-end="1128">First, the new architecture is <strong data-start="591" data-end="637">robust to Google Colab environment updates</strong>. All critical dependencies—Python (≥3.12), NumPy (≥2.0), PyTorch (2.x), CUDA wheels, and BitsAndBytes quantization—are now managed through Hugging Face Transformers and its dependency resolution. Because the model code, processor logic, and quantization pathways are maintained upstream, updates to Colab or its underlying libraries no longer break the inference pipeline. As long as Hugging Face continues to support the model card, the code remains functional without manual intervention.</p>
<p style="text-align: justify;" data-start="1130" data-end="1617">Second, the system relies exclusively on <strong data-start="1171" data-end="1218">official Hugging Face–maintained components</strong>. Core classes such as <code data-start="1241" data-end="1276"><span style="font-size: 10.0pt;">LlavaNextForConditionalGeneration</span></code>, <code data-start="1278" data-end="1298"><span style="font-size: 10.0pt;">LlavaNextProcessor</span></code>, chat templates, and multimodal preprocessing logic are all part of the Transformers library. These components are actively maintained, versioned, and tested by Hugging Face, providing a level of stability and backward compatibility that is not guaranteed when relying on research repositories or development branches.</p>
<p style="text-align: justify;" data-start="1619" data-end="2162">Third, the new setup significantly improves <strong data-start="1663" data-end="1682">reproducibility</strong>. Each run explicitly references a fixed Hugging Face model checkpoint via the <code data-start="1761" data-end="1771"><span style="font-size: 10.0pt;">model_id</span></code>, ensuring that the same weights, architecture, and prompt template are used across sessions and machines. In addition, generation parameters (sampling strategy, temperature, nucleus sampling, and output length) are explicitly defined, enabling consistent and repeatable results across runs.</p>
<p style="text-align: justify;" data-start="2164" data-end="2626">Fourth, the architecture is <strong data-start="2192" data-end="2230">easy to extend and experiment with</strong>. Switching between different LLaVA variants now requires changing a single configuration line (<code data-start="2326" data-end="2336"><span style="font-size: 10.0pt;">model_id</span></code>). The same inference code supports LLaVA 1.5 models, LLaVA-NeXT (v1.6), Interleave models, OneVision models, and larger checkpoints (e.g., 13B or 34B), including variants based on Mistral, Vicuna, Qwen, or Yi backbones. No changes to prompt construction or forward-pass logic are required.</p>
<p style="text-align: justify;" data-start="2628" data-end="3091">Finally, the multimodal pipeline is now <strong data-start="2668" data-end="2716">cleanly abstracted and internally consistent</strong>. Hugging Face handles all low-level details, including image preprocessing, chat formatting, positional embeddings, image sequence length management, and attention masking. This eliminates a large class of subtle bugs related to tensor alignment and multimodal token placement, while ensuring that the vision and language components remain synchronized across model updates.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-5 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);">4. References and links</h2></div><div class="fusion-text fusion-text-7 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><ul>
<li style="text-align: justify;">
<p class="heading-element" dir="auto" tabindex="-1">Streetscape Analysis with Generative AI (SAGAI) on Github with v1.1 update. <a class="keychainify-checked" href="https://github.com/perezjoan/SAGAI">https://github.com/perezjoan/SAGAI</a></p>
</li>
<li>Perez, J and Fusco, G. (2025) <em>Streetscape Analysis with Generative AI (SAGAI): Vision-Language Assessment and Mapping of Urban Scenes</em>. Geomatica, 77(2), 100063, 18p. Available at: <a class="keychainify-checked" href="https://www.sciencedirect.com/science/article/pii/S1195103625000199" rel="nofollow">https://www.sciencedirect.com/science/article/pii/S1195103625000199</a></li>
</ul>
</div></div></div><div class="fusion-layout-column fusion_builder_column fusion-builder-column-1 awb-sticky awb-sticky-medium awb-sticky-large fusion_builder_column_1_4 1_4 fusion-flex-column" style="--awb-padding-top:20px;--awb-padding-right:20px;--awb-padding-bottom:20px;--awb-padding-left:20px;--awb-bg-size:cover;--awb-border-color:var(--awb-color6);--awb-border-style:solid;--awb-width-large:25%;--awb-margin-top-large:0px;--awb-spacing-right-large:7.68%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:7.68%;--awb-width-medium:25%;--awb-order-medium:0;--awb-spacing-right-medium:7.68%;--awb-spacing-left-medium:7.68%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;--awb-sticky-offset:150px;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-8"><p><span style="color: #143c4e;"><strong>Table of contents</strong></span></p>
</div><div class="awb-toc-el awb-toc-el--1" data-awb-toc-id="1" data-awb-toc-options="{&quot;allowed_heading_tags&quot;:{&quot;h2&quot;:0},&quot;ignore_headings&quot;:&quot;&quot;,&quot;ignore_headings_words&quot;:&quot;&quot;,&quot;enable_cache&quot;:&quot;no&quot;,&quot;highlight_current_heading&quot;:&quot;yes&quot;,&quot;hide_hidden_titles&quot;:&quot;no&quot;,&quot;limit_container&quot;:&quot;page_content&quot;,&quot;select_custom_headings&quot;:&quot;.contenu H2, .contenu H3&quot;,&quot;icon&quot;:&quot;fa-flag fas&quot;,&quot;counter_type&quot;:&quot;none&quot;}" style="--awb-item-padding-right:5px;--awb-item-padding-left:5px;"><div class="awb-toc-el__content"></div></div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:20px;margin-bottom:20px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div></div></div></div></div>
<p>The post <a href="https://urbangeoanalytics.com/a-stable-and-reproducible-vision-language-inference-engine-for-sagai-v1-1/">A Stable and Reproducible Vision–Language Inference Engine for SAGAI v1.1</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://urbangeoanalytics.com/a-stable-and-reproducible-vision-language-inference-engine-for-sagai-v1-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Exploring Spatial Patterns of Point Distributions using NDD and CSR</title>
		<link>https://urbangeoanalytics.com/exploring-csr-for-spatial-patterns-of-points/</link>
					<comments>https://urbangeoanalytics.com/exploring-csr-for-spatial-patterns-of-points/#respond</comments>
		
		<dc:creator><![CDATA[Joan Perez]]></dc:creator>
		<pubDate>Mon, 15 Apr 2024 15:01:42 +0000</pubDate>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[Point Pattern Analysis]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Complete spatial randomness]]></category>
		<category><![CDATA[CSR]]></category>
		<category><![CDATA[GeoPandas]]></category>
		<category><![CDATA[nearest neighbor distance]]></category>
		<category><![CDATA[Spatial Analysis]]></category>
		<category><![CDATA[urban analysis]]></category>
		<guid isPermaLink="false">https://urbangeoanalytics.com/?p=37</guid>

					<description><![CDATA[<p>Calculating Nearest Neighbor Distance (NND) and comparing it with Complete Spatial Randomness (CSR) can be useful in various fields.  In this tutorial, we will see together how to calculate a nearest neighbor distance from a given point pattern and compare it to a random distribution (CSR).</p>
<p>The post <a href="https://urbangeoanalytics.com/exploring-csr-for-spatial-patterns-of-points/">Exploring Spatial Patterns of Point Distributions using NDD and CSR</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box fusion-builder-row-2 fusion-flex-container has-pattern-background has-mask-background nonhundred-percent-fullwidth non-hundred-percent-height-scrolling" style="--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;" id="contenu" ><div class="fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap" style="max-width:1248px;margin-left: calc(-4% / 2 );margin-right: calc(-4% / 2 );"><div class="fusion-layout-column fusion_builder_column fusion-builder-column-2 fusion_builder_column_3_4 3_4 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:75%;--awb-margin-top-large:0px;--awb-spacing-right-large:2.56%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:2.56%;--awb-width-medium:75%;--awb-order-medium:0;--awb-spacing-right-medium:2.56%;--awb-spacing-left-medium:2.56%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" id="contenu" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-9"><h5><strong>Highlights</strong></h5>
</div><div class="fusion-text fusion-text-10" style="--awb-margin-top:-30px;"><ul>
<li><b>Data Preparation:</b> Point data preparation using the Python library GeoPandas</li>
<li><b>Calculating NND and generating CSR distribution:</b> Nearest Neighbor Distance and generation of random points for comparison</li>
<li><b>Interpreting Results:</b> Comparison of observed NND values with CSR, indicating clustering, dispersion, or randomness</li>
<li><b>Comparative Analysis:</b> Comparative analysis example using two cities in Italy : Grosseto and Sinalunga</li>
</ul>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-6 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="48" data-lineheight="57.6px">1. Complete Spatial Randomness : Theoretical Recap</p></h2></div><div class="fusion-text fusion-text-11 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>CSR, or Complete Spatial Randomness, is a theoretical model used in spatial statistics to describe a random distribution of points in space. Essentially, in a CSR process, points are distributed randomly across the study area, with no clustering or spatial patterns. Each point is independent of the others and has an equal chance of occurring at any location within the study area.</p>
<p>When comparing observed spatial patterns to CSR, it is important to note that if the observed pattern exhibits a mean nearest neighbor distance that is significantly smaller than the mean nearest neighbor distance of a random distribution (CSR), it suggests clustering. In other words, this means that points in the observed pattern are closer to each other on average than would be expected under a random process. Conversely, if the mean nearest neighbor distance of the observed pattern is significantly larger than that of a random distribution, it suggests dispersion. Consequently, this indicates that points in the observed pattern are farther apart on average than would be expected under a random process.</p>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-2" style="text-align:center;--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-2 hover-type-none"><img decoding="async" width="800" height="565" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/AM07_Fig3-1.png" alt class="img-responsive wp-image-1706" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/AM07_Fig3-1-200x141.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/AM07_Fig3-1-400x283.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/AM07_Fig3-1-600x424.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/AM07_Fig3-1.png 800w" sizes="(max-width: 640px) 100vw, 800px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"><div class="awb-imageframe-caption-title">Figure 1 : Interpretation of Patterns from mean NND score (Source : Yuan et al., 2020)</div></div></div></div><div class="fusion-text fusion-text-12 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Calculating Nearest Neighbor Distance (NND) and comparing it with CSR can be useful in various fields where spatial patterns play a crucial role, such as ecology (distribution of species) or urban planning. Let&#8217;s see together how to calculate a nearest neighbor distance from a given point pattern and compare it to a random distribution (CSR).</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-7 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="48" data-lineheight="57.6px">2. Spatial patterns of points : calculation of Nearest Neighbor Distance (NND) and comparison with CSR</p></h2></div><div class="fusion-title title fusion-title-8 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">2.1 Spatial patterns of points : Sample data</p></h2></div><div class="fusion-text fusion-text-13 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>To perform this analysis, we will use two building layers. You can obtain OSM building data from various locations worldwide using the <a class="keychainify-checked" href="https://overpass-turbo.eu/#">Overpass Turbo tool</a>. The sample data used in this demonstration consists of two OSM building layers compiled into a Geopackage file.</p>
</div><div style="text-align:center;"><a class="fusion-button button-flat fusion-button-default-size button-lightgray fusion-button-lightgray button-1 fusion-button-default-span fusion-button-default-type" target="_self" href="https://urbangeoanalytics.com/wp-content/uploads/2024/04/Italian_cities.7z"><div class="awb-button__hover-content awb-button__hover-content--default awb-button__hover-content--centered"><span class="fusion-button-text awb-button__text awb-button__text--default">Download Italian Cities (GPKG)</span><span class="fusion-button-text awb-button__text awb-button__text--hover">Download Italian Cities (GPKG)</span></div></a></div><div class="fusion-text fusion-text-14 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>This sample data pertains specifically to the Italian cities of Grosseto and Sinalunga, each containing approximately 7500 buildings.</p>
</div><div class="fusion-text fusion-text-15 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="dracula" data-enlighter-group="Python1" data-enlighter-title="Python1">import geopandas as gpd
import numpy as np
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt

# Read the layers for the two Italian cities
gdf_1 = gpd.read_file("Italian_cities.gpkg", layer = "Grosseto")
gdf_1 = gdf_1.to_crs(epsg=6875)
gdf_2 = gpd.read_file("Italian_cities.gpkg", layer = "Sinalunga")
gdf_2 = gdf_2.to_crs(epsg=6875)</pre>
<p>&nbsp;</p>
</div><div class="fusion-text fusion-text-16 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The provided code imports necessary libraries and extracts each layer from the GeoPackage. For detailed guidance on configuring your Python environment and managing libraries, you can consult this <a class="keychainify-checked" href="https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/">post</a>. Additionally, if you seek information on GeoPackage usage and layer importation into Python, you can refer to this <a href="https://urbangeoanalytics.com/geopackage-and-how-to-import-them-in-r-using-sf-and-python-using-geopandas/">post</a>.</p>
</div><div class="fusion-text fusion-text-17 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="dracula" data-enlighter-group="Python2" data-enlighter-title="Python"># Create a figure with two subplots
fig, axs = plt.subplots(1, 2, figsize=(20, 10))

# Plot gdf_1 in the first subplot
gdf_1.plot(ax=axs[0], color='blue', edgecolor='black')
axs[0].set_title("Map View of Grosseto")
axs[0].set_xlabel("Longitude")
axs[0].set_ylabel("Latitude")

# Plot gdf_2 in the second subplot
gdf_2.plot(ax=axs[1], color='red', edgecolor='black')
axs[1].set_title("Map View of Sinalunga")
axs[1].set_xlabel("Longitude")
axs[1].set_ylabel("Latitude")

# Adjust layout
plt.tight_layout()

# Display the plot
plt.show()</pre>
<p>&nbsp;</p>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-3" style="text-align:center;--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-3 hover-type-none"><img decoding="async" width="1024" height="454" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1.png" alt class="img-responsive wp-image-1711" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1-200x89.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1-400x177.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1-600x266.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1-800x355.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1024x454-1.png 1024w" sizes="(max-width: 640px) 100vw, 1024px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"></div></div></div><div class="fusion-text fusion-text-18 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>This code snippet creates a figure with two subplots. Specifically, in the first subplot, the map view of Grosseto is plotted, while Sinalunga is shown in the second plot. At first glance, buildings in both maps look clustered. However, it is difficult to visually assess which pattern is more clustered or dispersed than the other.</p>
</div><div class="fusion-title title fusion-title-9 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">2.2 Generating a Distribution of Random Points</p></h2></div><div class="fusion-text fusion-text-19 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="dracula" data-enlighter-group="Python3" data-enlighter-title="Python"># Calculate the centroids of gdf_1
gdf_1_points = gdf_1.centroid
points_geom = gpd.GeoDataFrame(geometry=gdf_1_points)
# Extract coordinates from the centroids
coordinates = np.array([[points.coords[0][0], points.coords[0][1]] for points in points_geom.geometry])

# Calculate the bounding box of the GeoDataFrame
min_x, min_y, max_x, max_y = gdf_1.total_bounds
np.random.seed(123)  # Set seed for reproducibility

# Generate random points within the bounding box
random_points_x = np.random.uniform(min_x, max_x, 1000)
random_points_y = np.random.uniform(min_y, max_y, 1000)
# Create a GeoDataFrame from the random points
random_points_geom = gpd.GeoDataFrame(geometry=gpd.points_from_xy(random_points_x, random_points_y))

# Extract coordinates of the random points
coordinates_random = np.array([[point.x, point.y] for point in random_points_geom.geometry])

# Plot the random points
ax = random_points_geom.plot(markersize=1)
ax.set_title('Random Points Plot')
plt.show()</pre>
<p>&nbsp;</p>
</div><div class="fusion-builder-row fusion-builder-row-inner fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap" style="width:104% !important;max-width:104% !important;margin-left: calc(-4% / 2 );margin-right: calc(-4% / 2 );"><div class="fusion-layout-column fusion_builder_column_inner fusion-builder-nested-column-0 fusion_builder_column_inner_1_2 1_2 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:25px;--awb-spacing-right-large:3.84%;--awb-margin-bottom-large:25px;--awb-spacing-left-large:3.84%;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:3.84%;--awb-spacing-left-medium:3.84%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-20" style="--awb-content-alignment:justify;"><p>This code snippet demonstrates the process of generating random points within the bounding box of a given GeoDataFrame, which contains geographical data. To begin with, the centroids of the GeoDataFrame are calculated to determine the central points of each building, thus transforming the buildings into spatial patterns of points. Next, the total bounds of the GeoDataFrame are computed to define the bounding box, which encompasses all geometries. Subsequently, using the minimum and maximum coordinates of the bounding box, random points are generated uniformly within this spatial extent. After that, these random points are then organized into a GeoDataFrame for further analysis. Overall, this approach is commonly used in spatial analysis and simulation studies to simulate spatial processes or to create synthetic datasets for testing algorithms and methods.</p>
</div></div></div><div class="fusion-layout-column fusion_builder_column_inner fusion-builder-nested-column-1 fusion_builder_column_inner_1_2 1_2 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:25px;--awb-spacing-right-large:3.84%;--awb-margin-bottom-large:25px;--awb-spacing-left-large:3.84%;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:3.84%;--awb-spacing-left-medium:3.84%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-image-element " style="--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-4 hover-type-none"><img decoding="async" width="640" height="582" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-2-1.png" alt class="img-responsive wp-image-1716" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-2-1-200x182.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-2-1-400x364.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-2-1-600x546.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-2-1.png 640w" sizes="(max-width: 640px) 100vw, 600px" /></span></div></div></div></div><div class="fusion-text fusion-text-21 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-group="Python4" data-enlighter-title="Python" data-enlighter-theme="dracula"># Function to calculate nearest neighbor distances
def nearest_neighbor_distances(points):
    # Calculate pairwise distances between points
    distances = cdist(points, points)
    np.fill_diagonal(distances, np.inf)  # Exclude distance to itself
    # Calculate nearest neighbor distances
    nearest_distances = np.min(distances, axis=1)
    return nearest_distances

# SD on the nearest neighbor distances
def nearest_neighbor_sd(points):
    # Calculate nearest neighbor distances
    nearest_distances = nearest_neighbor_distances(points)
    # Calculate standard deviation of nearest neighbor distances
    sd = np.std(nearest_distances)
    return sd</pre>
<p>&nbsp;</p>
</div><div class="fusion-text fusion-text-22 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The <code>nearest_neighbor_distances</code> function calculates the nearest neighbor distances for a given set of points in a two-dimensional space. Specifically, it computes the pairwise distances between all points using the <code>cdist</code> function from SciPy&#8217;s spatial module. After that, by filling the diagonal of the distance matrix with infinity, it excludes distances to the points themselves. Consequently, it finds the minimum distance for each point, representing its nearest neighbor distance. Finally, the function returns an array containing the nearest neighbor distance for each point. This array is then used by the <code>nearest_neighbor_sd</code> function, which computes the standard deviation of nearest neighbor distances for a set of points.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-10 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="toc_3_Results_and_Interpretation_of_NDD_and_CSR" class="fusion-responsive-typography-calculated" data-fontsize="48" data-lineheight="57.6px">3. Results and Interpretation of NDD and CSR results for spatial patterns of points</p></h2></div><div class="fusion-title title fusion-title-11 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">3.1 Assess clustering or dispersion</p></h2></div><div class="fusion-text fusion-text-23 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-group="Python5" data-enlighter-title="Python" data-enlighter-theme="dracula">mean_observed_nn = np.mean(nearest_neighbor_distances(coordinates))
mean_random_nn = np.mean(nearest_neighbor_distances(coordinates_random))
std_random_nn = nearest_neighbor_sd(coordinates_random)

# Calculate threshold of within CSR (-1/2 +1/2 sd)
lower_bound = mean_random_nn - 0.5 * std_random_nn
upper_bound = mean_random_nn + 0.5 * std_random_nn

# Assess clustering or dispersion
if mean_observed_nn &lt; lower_bound:
    print(f"The observed point pattern (mean: ) is significantly clustered compared to the random pattern (mean: ).")
elif mean_observed_nn &gt; upper_bound:
    print(f"The observed point pattern (mean: ) is significantly dispersed compared to the random pattern (mean: ).")
else:
    print(f"The observed point pattern (mean: ) is consistent with CSR (mean random: ).")</pre>
<pre class="wp-block-preformatted has-secondary-background-color has-background">The observed point pattern (mean: 24.73) is significantly clustered compared to the random pattern (mean: 47.95).</pre>
</div><div class="fusion-text fusion-text-24 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The code calculates the mean nearest neighbor distances for both an observed set of coordinates and a randomly generated set. Additionally, it computes the standard deviation (sd) of the nearest neighbor distances for the randomly generated set. These values are then used to establish thresholds for Complete Spatial Randomness (CSR). To detect clustered and dispersed patterns, lower and upper bounds are set using statistical principles: approximately 68% of data points fall within one standard deviation of the mean in a normal distribution. Hence, these bounds are established using half the standard deviation away from the mean of the random distances.</p>
<p>It is then possible to assess whether the observed point pattern exhibits clustering, dispersion, or adherence to CSR. If the mean nearest neighbor distance of the observed pattern falls below the lower bound, it indicates significant clustering compared to the random pattern. Conversely, if it exceeds the upper bound, it suggests significant dispersion. Otherwise, if the mean observed distance lies within the bounds, the point pattern is deemed consistent with CSR. The buildings of the city of Grosseto exhibit a significantly clustered pattern as compared to a random pattern. But how another city like Sinalunga compares to Grosseto?</p>
</div><div class="fusion-text fusion-text-25 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-group="Python6" data-enlighter-title="Python" data-enlighter-theme="dracula"># Calculate the centroids of the GeoDataFrame
gdf_2_points = gdf_2.centroid
# Create a GeoDataFrame from the centroids
points_geom2 = gpd.GeoDataFrame(geometry=gdf_2_points)
# Extract coordinates from the centroids
coordinates2 = np.array([[points.coords[0][0], points.coords[0][1]] for points in points_geom2.geometry])
mean_observed_nn2 = np.mean(nearest_neighbor_distances(coordinates2))
# Compare mean nearest neighbor distances
if mean_observed_nn2 &lt; mean_observed_nn:
    print("The values for the second city are more clustered.")
    print(f"Mean nearest neighbor distance for observed points in the first city: ")
    print(f"Mean nearest neighbor distance for observed points in the second city: ")
else:
    print("The values for the second city are more dispersed.")
    print(f"Mean nearest neighbor distance for observed points in the first city: ")
    print(f"Mean nearest neighbor distance for observed points in the second city: ")</pre>
<pre class="wp-block-preformatted has-secondary-background-color has-background">The values for the second city are more clustered.
Mean nearest neighbor distance for observed points in the first city: 24.73
Mean nearest neighbor distance for observed points in the second city: 19.96</pre>
</div><div class="fusion-title title fusion-title-12 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">3.2 Comparing two Cities</p></h2></div><div class="fusion-text fusion-text-26 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The code compares the mean nearest neighbor distances between the first city and the second city. If the mean distance for the second city is less than that of the first city, indicating greater clustering, a message is printed to convey this observation along with the respective mean distances for both cities. Conversely, if the mean distance for the second city is greater, suggesting more dispersion, another message is printed with the corresponding mean distances for both cities. The results suggest that the buildings of Sinalunga are more clustered than the ones in Grosseto.</p>
</div><div class="fusion-text fusion-text-27 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-group="Python7" data-enlighter-title="Python" data-enlighter-theme="dracula"># Plot histograms of nearest neighbor distances
plt.figure(figsize=(10, 6))
plt.hist(nearest_neighbor_distances(coordinates), bins=50, color='blue', alpha=0.5, label='Grosseto')
plt.hist(nearest_neighbor_distances(coordinates2), bins=50, color='green', alpha=0.5, label='Sinalunga')
plt.hist(nearest_neighbor_distances(coordinates_random), bins=50, color='red', alpha=0.5, label='Random CSR')
plt.xlabel('Nearest Neighbor Distance')
plt.ylabel('Frequency')
plt.title('Nearest Neighbor Distance Distribution')
plt.legend()
plt.show()</pre>
<p>&nbsp;</p>
</div><div class="fusion-builder-row fusion-builder-row-inner fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap" style="width:104% !important;max-width:104% !important;margin-left: calc(-4% / 2 );margin-right: calc(-4% / 2 );"><div class="fusion-layout-column fusion_builder_column_inner fusion-builder-nested-column-2 fusion_builder_column_inner_1_2 1_2 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:25px;--awb-spacing-right-large:3.84%;--awb-margin-bottom-large:25px;--awb-spacing-left-large:3.84%;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:3.84%;--awb-spacing-left-medium:3.84%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-28" style="--awb-content-alignment:justify;"><p>Finally, we can display an histogram comparing the random distribution with the NDD values of each point for Grosseto and Sinalunga. Overall, this approach can be useful for various analytical purposes, such as comparing whether a subset of data is more or less clustered than the main dataset (e.g., a subset containing missing values) or for examining specific typologies within a dataset. It could also be interesting to compare the results of a single city at different periods. A lower score between two periods would suggest a densification process, whereas a larger score would indicate a dynamic of urban sprawl.</p>
</div></div></div><div class="fusion-layout-column fusion_builder_column_inner fusion-builder-nested-column-3 fusion_builder_column_inner_1_2 1_2 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:50%;--awb-margin-top-large:25px;--awb-spacing-right-large:3.84%;--awb-margin-bottom-large:25px;--awb-spacing-left-large:3.84%;--awb-width-medium:50%;--awb-order-medium:0;--awb-spacing-right-medium:3.84%;--awb-spacing-left-medium:3.84%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-image-element " style="--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-5 hover-type-none"><img decoding="async" width="938" height="585" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1.png" alt class="img-responsive wp-image-1719" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1-200x125.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1-400x249.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1-600x374.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1-800x499.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-1-1.png 938w" sizes="(max-width: 640px) 100vw, 600px" /></span></div></div></div></div><div class="fusion-title title fusion-title-13 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="toc_References_to_go_further" class="fusion-responsive-typography-calculated" data-fontsize="48" data-lineheight="57.6px">References &amp; to go further</p></h2></div><div class="fusion-text fusion-text-29 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><ul>
<li><a class="keychainify-checked" href="https://geographicdata.science/book/notebooks/08_point_pattern_analysis.html">Point Pattern Analysis – Geographic Data Science</a></li>
<li>Yuan, Y., Qiang, Y., Bin Asad, K., and Chow, T. E. (2020). Point Pattern Analysis. The Geographic Information Science &amp; Technology Body of Knowledge (1st Quarter 2020 Edition), John P. Wilson (ed.). DOI: 10.22224/gistbok/2020.1.13.</li>
<li>Usui, H and Perez, J. (2020) « Are patterns of vacant lots random? Evidence from empirical spatiotemporal analysis in Chiba prefecture, east of Tokyo », Environment and Planning B: Urban Analytics and City Science, 49(3). <a class="keychainify-checked" href="https://journals.sagepub.com/doi/abs/10.1177/2399808320956656">Read more</a></li>
</ul>
</div></div></div><div class="fusion-layout-column fusion_builder_column fusion-builder-column-3 awb-sticky awb-sticky-medium awb-sticky-large fusion_builder_column_1_4 1_4 fusion-flex-column" style="--awb-padding-top:20px;--awb-padding-right:20px;--awb-padding-bottom:20px;--awb-padding-left:20px;--awb-bg-size:cover;--awb-border-color:var(--awb-color6);--awb-border-style:solid;--awb-width-large:25%;--awb-margin-top-large:0px;--awb-spacing-right-large:7.68%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:7.68%;--awb-width-medium:25%;--awb-order-medium:0;--awb-spacing-right-medium:7.68%;--awb-spacing-left-medium:7.68%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;--awb-sticky-offset:150px;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-30"><p> <span style="color: #143c4e;"><strong>Table of contents</strong></span> </p>
</div><div class="awb-toc-el awb-toc-el--2" data-awb-toc-id="2" data-awb-toc-options="{&quot;allowed_heading_tags&quot;:{&quot;h2&quot;:0},&quot;ignore_headings&quot;:&quot;&quot;,&quot;ignore_headings_words&quot;:&quot;&quot;,&quot;enable_cache&quot;:&quot;no&quot;,&quot;highlight_current_heading&quot;:&quot;yes&quot;,&quot;hide_hidden_titles&quot;:&quot;no&quot;,&quot;limit_container&quot;:&quot;page_content&quot;,&quot;select_custom_headings&quot;:&quot;.contenu H2, .contenu H3&quot;,&quot;icon&quot;:&quot;fa-flag fas&quot;,&quot;counter_type&quot;:&quot;none&quot;}" style="--awb-item-padding-right:5px;--awb-item-padding-left:5px;"><div class="awb-toc-el__content"></div></div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:20px;margin-bottom:20px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-image-element " style="--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);--awb-filter:saturate(100%);--awb-filter-transition:filter 0.3s ease;--awb-filter-hover:saturate(0%);"><span class=" fusion-imageframe imageframe-none imageframe-6 hover-type-zoomout"><img decoding="async" width="1536" height="1024" src="https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3.png" alt class="img-responsive wp-image-1688" srcset="https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3-200x133.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3-400x267.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3-600x400.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3-800x533.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3-1200x800.png 1200w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl3.png 1536w" sizes="(max-width: 640px) 100vw, 400px" /></span></div></div></div></div></div>
<p>The post <a href="https://urbangeoanalytics.com/exploring-csr-for-spatial-patterns-of-points/">Exploring Spatial Patterns of Point Distributions using NDD and CSR</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://urbangeoanalytics.com/exploring-csr-for-spatial-patterns-of-points/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Getting Started with Python using Anaconda and Jupyter Notebook</title>
		<link>https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/</link>
					<comments>https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/#respond</comments>
		
		<dc:creator><![CDATA[Joan Perez]]></dc:creator>
		<pubDate>Fri, 12 Apr 2024 09:00:59 +0000</pubDate>
				<category><![CDATA[Getting Started]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Anaconda]]></category>
		<category><![CDATA[Contextily]]></category>
		<category><![CDATA[GeoPandas]]></category>
		<category><![CDATA[Jupyter Notebook]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Pyogrio]]></category>
		<category><![CDATA[Python Environment]]></category>
		<category><![CDATA[Spatial Analysis]]></category>
		<guid isPermaLink="false">https://urbangeoanalytics.com/?p=119</guid>

					<description><![CDATA[<p>In this guide you'll find clear instructions on setting up Python with Anaconda for spatial analysis. Then, we'll cover installing Python alongside Anaconda and adding essential dependencies like GeoPandas via the Anaconda Prompt. Lastly, we'll explore using the Jupyter Notebook for practical application.</p>
<p>The post <a href="https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/">Getting Started with Python using Anaconda and Jupyter Notebook</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box fusion-builder-row-3 fusion-flex-container has-pattern-background has-mask-background nonhundred-percent-fullwidth non-hundred-percent-height-scrolling" style="--awb-border-radius-top-left:0px;--awb-border-radius-top-right:0px;--awb-border-radius-bottom-right:0px;--awb-border-radius-bottom-left:0px;--awb-flex-wrap:wrap;" id="contenu" ><div class="fusion-builder-row fusion-row fusion-flex-align-items-flex-start fusion-flex-content-wrap" style="max-width:1248px;margin-left: calc(-4% / 2 );margin-right: calc(-4% / 2 );"><div class="fusion-layout-column fusion_builder_column fusion-builder-column-4 fusion_builder_column_3_4 3_4 fusion-flex-column" style="--awb-bg-size:cover;--awb-width-large:75%;--awb-margin-top-large:0px;--awb-spacing-right-large:2.56%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:2.56%;--awb-width-medium:75%;--awb-order-medium:0;--awb-spacing-right-medium:2.56%;--awb-spacing-left-medium:2.56%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;" id="contenu" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-31"><h5><strong>Highlights</strong></h5>
</div><div class="fusion-text fusion-text-32" style="--awb-margin-top:-40px;"><ul>
<li><strong data-start="64" data-end="88">Easy Python Setup: </strong>Learn how to install Python using Anaconda and configure a full environment for spatial analysis in just a few steps.</li>
<li><strong data-start="210" data-end="235">Spatial Data Ready: </strong>Install essential libraries like GeoPandas, Pyogrio, and Contextily to start working with geospatial datasets immediately.</li>
<li><strong data-start="362" data-end="384">Work in Jupyter:</strong>Use Jupyter Notebooks to write, visualize, and run spatial analysis code directly — perfect for beginners and researchers alike.</li>
</ul>
</div><div class="fusion-text fusion-text-33 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>In this guide you’ll find clear instructions on setting up Python with Anaconda for spatial analysis. Then, we’ll cover installing Python alongside Anaconda and adding essential dependencies like GeoPandas via the Anaconda Prompt. Lastly, we’ll explore using the Jupyter Notebook for practical application. By the end, you’ll be ready to start your journey in Python-based spatial analysis, AI, and machine learning.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-14 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="toc_1_Install_Python_with_Anaconda" class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">1. Install Python with Anaconda</p></h2></div><div class="fusion-text fusion-text-34 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Anaconda is a powerful tool for managing Python environments. Indeed, Anaconda simplifies package management through its <b>integrated package manager, conda</b>. In addition, it comes bundled with a set of pre-installed libraries commonly used in data science and spatial analysis, such as NumPy, Pandas or Matplotlib. Therefore, this eliminates the need for manual installation and ensures immediate access to these libraries. Anaconda is also cross-platform compatible (available for Windows, macOS, and Linux) thus providing consistent Python environments across different operating systems. Furthermore, it seamlessly integrates with popular development environments like <b>Jupyter Notebook</b>, known amongst other things for its user-friendly interface. Visit the <a class="keychainify-checked" href="https://www.anaconda.com/download">Anaconda website</a> and download the Anaconda distribution related to your operating system (Windows, macOS, or Linux). Once Anaconda is installed, you’ll have access to the Anaconda Navigator, Anaconda Prompt, and other useful tools for managing Python environments.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-15 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="1" class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">2. Install Additional Dependencies on Python using Anaconda Prompt</p></h2></div><div class="fusion-text fusion-text-35 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Even if the Python distribution installed by Anaconda comes with numerous pre-installed libraries, additional dependencies will be required to enable performing advanced manipulations, and this is especially true for manipulating spatial data. So, let’s install the following three dependencies to manipulate spatial data : <b>GeoPandas</b> : allow spatial operations on geometric types ; <b>Pyogrio</b> : interoperability between spatial data formats and <b>Contextily</b> : retrieve tile maps from the internet.<br />
Then, on Windows, click on the Start Menu and type “Anaconda Prompt” in the search bar and open it. This will open a new command prompt window with Anaconda enabled. Within the command prompt, run the following commands one by one to install the aforementioned dependencies.</p>
</div><div class="fusion-text fusion-text-36 fusion-text-no-margin" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><pre class="EnlighterJSRAW" data-enlighter-language="powershell" data-enlighter-theme="dracula" data-enlighter-group="PowerShell1" data-enlighter-title="PowerShell">conda install -c conda-forge geopandas 
conda install -c conda-forge pyogrio 
conda install -c conda-forge contextily</pre>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-7" style="text-align:center;--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-7 hover-type-none"><img decoding="async" width="999" height="325" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1.png" alt class="img-responsive wp-image-1418" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1-200x65.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1-400x130.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1-600x195.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1-800x260.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-4-1.png 999w" sizes="(max-width: 640px) 100vw, 999px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"><div class="awb-imageframe-caption-title">Opening the Ananconda prompt and installing dependencies – Example with GeoPandas</div></div></div></div><div class="fusion-text fusion-text-37 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>If you’ve previously installed the libraries, executing these lines will not only update the libraries themselves but also their dependencies. Additionally, any other dependencies not encompassed within the Anaconda distribution of Python can be installed using the same commands. For instance, for machine learning purposes, you can install ‘XGBoost’ (eXtreme Gradient Boosting) using these lines as well.</p>
</div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-16 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="toc_3_Open_Anaconda_Navigator_and_Launch_Jupyter_Notebook" class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">3. Open Anaconda Navigator and Launch Jupyter Notebook</p></h2></div><div class="fusion-text fusion-text-38 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Now that you’ve installed Python and the required dependencies, you can open the Anaconda Navigator and launch the Jupyter Notebook from the Home tab, as follows:</p>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-8" style="text-align:center;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-8 hover-type-none"><img decoding="async" width="1024" height="445" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1.png" alt class="img-responsive wp-image-1446" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1-200x87.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1-400x174.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1-600x261.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1-800x348.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-3-1024x445-1.png 1024w" sizes="(max-width: 640px) 100vw, 1024px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"></div></div></div><div class="fusion-text fusion-text-39 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Jupyter Notebook is an open-source web application that allows users to create and share documents containing live code, visualizations, and narrative text. Upon launching the notebook, you’ll be directed to the J<strong>upyter Notebook explorer </strong>in your default web browser, where you can create folders and new notebooks with a simple right-click action, as demonstrated below.</p>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-9" style="text-align:center;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-9 hover-type-none"><img decoding="async" width="1024" height="212" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1.png" alt class="img-responsive wp-image-1454" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1-200x41.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1-400x83.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1-600x124.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1-800x166.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-5-1024x212-1.png 1024w" sizes="(max-width: 640px) 100vw, 1024px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"></div></div></div><div class="fusion-text fusion-text-40 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Afterward, you can rename your notebook (indicated by <strong>arrow 1</strong> below). In a notebook, users can compose and execute code in segmented blocks. The figure below illustrates one such block (indicated by <strong>arrow 2 </strong>below).</p>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-10" style="text-align:center;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-10 hover-type-none"><img decoding="async" width="1024" height="283" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1.png" alt class="img-responsive wp-image-1456" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1-200x55.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1-400x111.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1-600x166.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1-800x221.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-6-1024x283-1.png 1024w" sizes="(max-width: 640px) 100vw, 1024px" /></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"></div></div></div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:25px;margin-bottom:25px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-title title fusion-title-17 fusion-sep-none fusion-title-text fusion-title-size-two" style="--awb-margin-top:25px;--awb-margin-bottom:25px;"><h2 class="fusion-title-heading title-heading-left fusion-responsive-typography-calculated" style="margin:0;--fontSize:48;line-height:var(--awb-typography1-line-height);"><p id="toc_4_Set_a_Working_Directory_and_Load_Data" class="fusion-responsive-typography-calculated" data-fontsize="36" data-lineheight="43.2px">4. Set a Working Directory and Load Data from Jupyter</p></h2></div><div class="fusion-text fusion-text-41 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Your notebook is automatically linked to the files within the folders where it resides. Let’s add some data to this folder and import it into the notebook (or Python environment). Begin by downloading the dataset provided below. This dataset comprises a GeoPackage file containing two building layers corresponding to two small cities in Italy: Grosseto and Sinalunga. For further insight related the GeoPackage format, you can refer to this <a class="keychainify-checked" href="https://urbangeoanalytics.com/?p=35">post.</a> Then, once you have downloaded, place it in the same directory as your notebook.</p>
</div><div style="text-align:center;"><a class="fusion-button button-flat fusion-button-default-size button-lightgray fusion-button-lightgray button-2 fusion-button-default-span fusion-button-default-type" target="_self" href="https://urbangeoanalytics.com/wp-content/uploads/2024/04/Italian_cities.7z"><div class="awb-button__hover-content awb-button__hover-content--default awb-button__hover-content--centered"><span class="fusion-button-text awb-button__text awb-button__text--default">Download Italian Cities (GPKG)</span><span class="fusion-button-text awb-button__text awb-button__text--hover">Download Italian Cities (GPKG)</span></div></a></div><div class="fusion-text fusion-text-42 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Then, you can run the code below to import a layer in Python using GeoPandas. In this example, we are importing a layer of building related to the italian city of Grosseto.</p>
</div><div class="fusion-text fusion-text-43"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-title="Python" data-enlighter-theme="dracula" data-enlighter-group="Python3">import geopandas as gpd 
Grosseto = gpd.read_file("Italian_cities.gpkg", layer = "Grosseto")</pre>
<p>&nbsp;</p>
</div><div class="fusion-text fusion-text-44 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>Finally, you can run the code below to plot the building layer with a basemap from OSM using contextily.</p>
</div><div class="fusion-text fusion-text-45"><pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-title="Python" data-enlighter-theme="dracula" data-enlighter-group="Python2">import matplotlib.pyplot as plt
import contextily as ctx

# Plot the Grosseto layer
fig, ax = plt.subplots(figsize=(10, 10))
Grosseto.plot(ax=ax, alpha=0.5)

# Add basemap using Contextily
ctx.add_basemap(ax, crs=Grosseto.crs, source=ctx.providers.CartoDB.Voyager)
# Set title and show plot
plt.title("Grosseto with Basemap")
plt.show()</pre>
</div><div class="fusion-image-element awb-imageframe-style awb-imageframe-style-below awb-imageframe-style-11" style="text-align:center;--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--body_typography-font-family);--awb-caption-title-font-weight:var(--body_typography-font-weight);--awb-caption-title-font-style:var(--body_typography-font-style);--awb-caption-title-size:var(--body_typography-font-size);--awb-caption-title-transform:var(--body_typography-text-transform);--awb-caption-title-line-height:var(--body_typography-line-height);--awb-caption-title-letter-spacing:var(--body_typography-letter-spacing);"><span class=" fusion-imageframe imageframe-none imageframe-11 hover-type-none"><a href="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1.png" class="fusion-lightbox" data-rel="iLightbox[7d3abab7bec15c57db5]"><img decoding="async" width="1024" height="678" src="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1.png" alt class="img-responsive wp-image-1465" srcset="https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1-200x132.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1-400x265.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1-600x397.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1-800x530.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2024/04/image-7-1024x678-1.png 1024w" sizes="(max-width: 640px) 100vw, 1024px" /></a></span><div class="awb-imageframe-caption-container" style="text-align:center;"><div class="awb-imageframe-caption"></div></div></div><div class="fusion-text fusion-text-46 fusion-text-no-margin" style="--awb-content-alignment:justify;--awb-margin-top:25px;--awb-margin-bottom:25px;"><p>The map above was generated using the Python code provided — demonstrating how to overlay geospatial data with a custom basemap using <code data-start="189" data-end="201">contextily</code>. Fell free to provide feedbacks on our blog posts by <a class="keychainify-checked" href="https://urbangeoanalytics.com/contact/"><strong>contacting us</strong></a>.</p>
</div></div></div><div class="fusion-layout-column fusion_builder_column fusion-builder-column-5 awb-sticky awb-sticky-medium awb-sticky-large fusion_builder_column_1_4 1_4 fusion-flex-column" style="--awb-padding-top:20px;--awb-padding-right:20px;--awb-padding-bottom:20px;--awb-padding-left:20px;--awb-bg-size:cover;--awb-border-color:var(--awb-color6);--awb-border-style:solid;--awb-width-large:25%;--awb-margin-top-large:0px;--awb-spacing-right-large:7.68%;--awb-margin-bottom-large:20px;--awb-spacing-left-large:7.68%;--awb-width-medium:25%;--awb-order-medium:0;--awb-spacing-right-medium:7.68%;--awb-spacing-left-medium:7.68%;--awb-width-small:100%;--awb-order-small:0;--awb-spacing-right-small:1.92%;--awb-spacing-left-small:1.92%;--awb-sticky-offset:150px;" data-scroll-devices="small-visibility,medium-visibility,large-visibility"><div class="fusion-column-wrapper fusion-column-has-shadow fusion-flex-justify-content-flex-start fusion-content-layout-column"><div class="fusion-text fusion-text-47"><p> <span style="color: #143c4e;"><strong>Table of contents</strong></span> </p>
</div><div class="awb-toc-el awb-toc-el--3" data-awb-toc-id="3" data-awb-toc-options="{&quot;allowed_heading_tags&quot;:{&quot;h2&quot;:0},&quot;ignore_headings&quot;:&quot;&quot;,&quot;ignore_headings_words&quot;:&quot;&quot;,&quot;enable_cache&quot;:&quot;no&quot;,&quot;highlight_current_heading&quot;:&quot;yes&quot;,&quot;hide_hidden_titles&quot;:&quot;no&quot;,&quot;limit_container&quot;:&quot;page_content&quot;,&quot;select_custom_headings&quot;:&quot;.contenu H2, .contenu H3&quot;,&quot;icon&quot;:&quot;fa-flag fas&quot;,&quot;counter_type&quot;:&quot;none&quot;}" style="--awb-item-padding-right:5px;--awb-item-padding-left:5px;"><div class="awb-toc-el__content"></div></div><div class="fusion-separator fusion-full-width-sep" style="align-self: center;margin-left: auto;margin-right: auto;margin-top:20px;margin-bottom:20px;width:100%;"><div class="fusion-separator-border sep-single sep-solid" style="--awb-height:20px;--awb-amount:20px;--awb-sep-color:var(--awb-color6);border-color:var(--awb-color6);border-top-width:1px;"></div></div><div class="fusion-image-element " style="--awb-margin-top:25px;--awb-margin-bottom:25px;--awb-caption-title-font-family:var(--h2_typography-font-family);--awb-caption-title-font-weight:var(--h2_typography-font-weight);--awb-caption-title-font-style:var(--h2_typography-font-style);--awb-caption-title-size:var(--h2_typography-font-size);--awb-caption-title-transform:var(--h2_typography-text-transform);--awb-caption-title-line-height:var(--h2_typography-line-height);--awb-caption-title-letter-spacing:var(--h2_typography-letter-spacing);--awb-filter:saturate(100%);--awb-filter-transition:filter 0.3s ease;--awb-filter-hover:saturate(0%);"><span class=" fusion-imageframe imageframe-none imageframe-12 hover-type-zoomout"><img decoding="async" width="1536" height="1024" title="blog lvl1" src="https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1.png" alt class="img-responsive wp-image-1685" srcset="https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1-200x133.png 200w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1-400x267.png 400w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1-600x400.png 600w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1-800x533.png 800w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1-1200x800.png 1200w, https://urbangeoanalytics.com/wp-content/uploads/2025/11/blog-lvl1.png 1536w" sizes="(max-width: 640px) 100vw, 400px" /></span></div></div></div></div></div>
<p>The post <a href="https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/">Getting Started with Python using Anaconda and Jupyter Notebook</a> appeared first on <a href="https://urbangeoanalytics.com">Urban Geo Analytics</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://urbangeoanalytics.com/setting-up-your-python-environment-for-spatial-analysis-ai-and-machine-learning-with-anaconda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
