> For the complete documentation index, see [llms.txt](https://docs.carto.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.carto.com/carto-user-manual/workflows/components/embedding-analytics.md).

# Analytics on Embeddings

An extension package for CARTO Workflows to analyze vector embeddings of places. Its components cover the whole path from raw embeddings to an answer: preparing the vectors, moving them to the spatial resolution you work at, comparing places against each other or against a baseline, tracking how places change over time, and rendering the result on a map.

Every component reads a table where each row is a place and the numeric columns are the dimensions of its embedding, so they work with embeddings derived from spatial data, satellite imagery, or any other geospatial source.

| To answer                                                           | Use                                               |
| ------------------------------------------------------------------- | ------------------------------------------------- |
| Which places look like this one?                                    | [Similarity Search](#similarity-search)           |
| Which places are unusual, compared to a baseline?                   | [Mean Deviation](#mean-deviation)                 |
| What natural groups do my places fall into?                         | [Clustering](#clustering)                         |
| How has a place changed over time?                                  | [Change Detection](#change-detection)             |
| Where does the embedding field change across space?                 | [Neighborhood Deviation](#neighborhood-deviation) |
| What does a brand, a store, or a catchment look like as one vector? | [Embedding Profile](#embedding-profile)           |
| How do I move embeddings from one geometry set to my own polygons?  | [Spatial Aggregation](#spatial-aggregation)       |
| How do I make the Dot product metric safe and cheap?                | [Vector Normalization](#vector-normalization)     |
| What do the embeddings look like on a map?                          | [Visualization](#visualization)                   |

{% hint style="info" %}
Unless a component says otherwise, every column in the input table except the ID column and the date column (if specified) is automatically used as an embedding vector dimension.
{% endhint %}

{% hint style="warning" %}
This extension package is available for **BigQuery** and **Snowflake** connections. Change Detection, Clustering, Similarity Search and Visualization are available on both. Embedding Profile, Mean Deviation, Neighborhood Deviation, Spatial Aggregation and Vector Normalization are available on BigQuery only. A few settings differ on Snowflake, as noted in each component.

On Snowflake, the dimensionality reduction and clustering run in Python UDFs (`numpy`, `scikit-learn`), so your Snowflake account must allow Python UDFs in order to use:

* **Clustering**, always.
* **Visualization**, with the default PCA reduction technique. Choosing **Manual** avoids it.
* **Change Detection** and **Similarity Search**, only when **Reduce embedding dimensionality** is enabled.
  {% endhint %}

{% hint style="warning" %}
**Updating from an earlier version on BigQuery.** Version 1.2.0 simplifies the existing components. Change Detection, Clustering and Similarity Search no longer reduce dimensionality with PCA. The Euclidean distance is gone: Change Detection and Similarity Search now offer Cosine and Dot product, and Clustering always uses cosine distance. Change Detection and Similarity Search no longer return a Metrics table.

After you update the extension package, update each outdated node, select the distance metric again where a node used Euclidean, and remove any connection from the Metrics output of Change Detection or Similarity Search.
{% endhint %}

{% hint style="success" %}
All components in this extension package work with embeddings resulting from using the components in the [Geospatial Foundation Models](/carto-user-manual/workflows/components/google-pdfm-embeddings.md) extension package.\
They also work with other embeddings as inputs, as long as each embedding feature is stored on a column (as opposed to an array of vectors).

The exception is [Neighborhood Deviation](#neighborhood-deviation), which only works with embeddings indexed by an H3 or Quadbin grid, because it compares each cell with its neighbors on that grid.
{% endhint %}

## Cosine and Dot product

On BigQuery, Change Detection, Mean Deviation, Neighborhood Deviation and Similarity Search compare vectors with one of two distance metrics. Both return the cosine distance, from 0 (same direction) to 2 (opposite direction).

**Cosine** normalizes the vectors itself, so it is correct whatever their length. If you do not know the magnitude of your embeddings, choose Cosine.

**Dot product** computes `1 - a·b` without normalizing the vectors, which skips two square roots and a division on every comparison. For unit-length vectors this is exactly the cosine distance, so both metrics return the same distances, the same scores and the same ranking. On vectors that are not unit length its results are meaningless rather than merely different, because a vector twice as long doubles its own score.

To use Dot product safely, run the [Vector Normalization](#vector-normalization) component once on your source table, or check whether your embeddings already have length 1 with a query like this:

```sql
SELECT MIN(norm) AS min_norm, MAX(norm) AS max_norm
FROM (
  SELECT SQRT((SELECT SUM(x * x) FROM UNNEST([emb_0, emb_1, ...]) AS x)) AS norm
  FROM `your_table`
)
```

If both values are 1, Dot product is safe. If they are not, use Cosine.

## Change Detection

**Description**

Analyzes temporal changes in embeddings by comparing vector representations across different time periods. It calculates distance metrics between consecutive time points for each location, enabling the identification of significant changes in spatial patterns, environmental conditions, or other time-varying characteristics encoded in the embeddings.

This component is particularly useful for monitoring temporal evolution, detecting anomalies, tracking environmental changes, and identifying locations that have undergone significant transformations over time.

**Inputs**

* **Embedding table**: Table containing the embeddings with associated timestamps and location identifiers.

**Settings**

* **ID column**: Column containing unique identifiers for each embedding. This column is used to track changes for the same entity across different time periods.
* **Date column**: Column containing the timestamps or dates associated with each embedding. This column is used to order the data chronologically and identify consecutive time periods for comparison.
* **Distance metric**: Distance function used to compare vectors across time, either **Cosine** or **Dot product** (default: Cosine). See [Cosine and Dot product](#cosine-and-dot-product) to choose between them.
* **Comparison method**: Determines how embeddings are compared across time (default: Rolling pairs).
  * **Rolling pairs**: Compares the embeddings of each timestamp with those of the previous time period, allowing you to track incremental changes over time. This mode is ideal for detecting gradual changes and trends.
  * **Cross pairs**: Compares the embeddings of each timestamp with all remaining time periods, providing a broader view of how a location evolves relative to any other time point. This mode is useful for identifying significant transformations and outliers.

**Outputs**

* **Output table**: The change detection table with the following columns:
  * `<geoid>`: Original identifier for each location/entity.
  * `<date>_from`: Starting timestamp for the change period.
  * `<date>_to`: Ending timestamp for the change period.
  * `distance`: Distance between the embeddings at the two time points.
  * `change_score`: Degree of change between the two embedding vectors of the same location. 0 means no change. On BigQuery it is computed as `distance / 2`, so 0.5 means orthogonal vectors and 1 a complete reversal.

{% hint style="info" %}
**On Snowflake**, the **Distance metric** offers **Cosine** and **Euclidean**. Euclidean measures the straight-line distance between vectors, so it accounts for their magnitude as well as their direction. Two more settings reduce the dimensionality of the embeddings with Principal Component Analysis (PCA) before the comparison: **Reduce embedding dimensionality** (default: false) and **PCA explained variance**, the share of the original variance to preserve (0.01-0.99, default: 0.9). The component also returns a **Metrics table** with `total_explained_variance_ratio` and `number_of_principal_components`.
{% endhint %}

{% hint style="warning" %}
The component requires complete temporal coverage for each location: every geoid must have embedding values for each date in the dataset. This ensures accurate change detection by maintaining consistent temporal baselines for comparison.
{% endhint %}

## Clustering

**Description**

Uses a K-means algorithm to group embeddings into k clusters, identifying locations with similar spatial patterns or features.

This component is particularly useful for discovering natural groupings in spatial data, segmenting areas based on their characteristics, and identifying outliers or distinct regions.

On BigQuery the clustering runs as a BigQuery ML `KMEANS` model directly on the embedding columns, with cosine distance and standardized features. On Snowflake it runs `scikit-learn`'s K-means inside a Python UDF. Neither implementation is seeded, so cluster IDs are arbitrary and the assignment of borderline points is not guaranteed to be identical between two runs of the same data, nor between the two warehouses.

**Inputs**

* **Embedding table**: Table containing the embeddings to cluster.

**Settings**

* **ID column**: Column containing unique identifiers for each embedding. This column is used to maintain the relationship between input embeddings and their assigned clusters in the output.
* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: Analyzes embeddings at a single point in time or without temporal considerations. Use this for static spatial pattern analysis.
  * **Spatio-temporal**: Analyzes embeddings across multiple time periods, enabling detection of temporal changes in spatial patterns. Requires a date column to be specified.
* **Date column**: Column containing temporal information for spatio-temporal analysis (required when Analysis type is Spatio-temporal). This column should contain date, datetime, timestamp, or numeric time values that identify when each embedding was captured.
* **Number of clusters**: Number of clusters to create (2-100, default: 5). This parameter determines how many groups the algorithm will divide your embeddings into.
* **Maximum iterations**: Maximum number of iterations for the K-means algorithm (1-1000, default: 20). The algorithm will stop after this many iterations even if it hasn't converged. Increase this value for complex datasets that may need more iterations to find optimal clusters.
* **Early stopping**: Whether to stop the algorithm early if it converges before reaching the maximum iterations (default: true). Enabling this improves performance by stopping as soon as cluster assignments stabilize, but may miss optimal solutions in some cases.
* **Minimum relative progress**: Threshold for early stopping convergence detection (0.001-0.1, default: 0.01). The algorithm stops when the improvement between iterations falls below this threshold. Lower values allow more precise convergence but may require more iterations.

**Outputs**

* **Output table**: The clustering table with the following columns:
  * `<geoid>`: Original identifier for each embedding.
  * `cluster_id`: Assigned cluster ID (1 to k).
  * `distance_to_centroid`: Distance from the embedding to its cluster centroid.
* **Metrics table**: The metrics table with the following columns:
  * `davies_bouldin_index`: A clustering quality metric that measures the ratio of within-cluster scatter to between-cluster separation. Lower values indicate better clustering quality, with values closer to 0 representing well-separated, compact clusters.
  * `mean_squared_distance`: The average squared distance from each point to its assigned cluster centroid. This metric helps assess how tightly packed the clusters are: lower values indicate more compact clusters.

{% hint style="info" %}
**On Snowflake**, a **Distance type** setting chooses the distance used for clustering: **EUCLIDEAN** (default) measures the straight-line distance between points, and **COSINE** measures the angle between vectors, ignoring their magnitude. Two more settings apply Principal Component Analysis (PCA) before clustering: **Reduce embedding dimensionality** (default: false) and **PCA explained variance**, the share of the original variance to preserve (0.01-0.99, default: 0.9). The metrics table adds `total_explained_variance_ratio` and `number_of_principal_components`.
{% endhint %}

## Embedding Profile

**Description**

Summarizes many location embeddings into one profile vector, the weighted mean of the embeddings, dimension by dimension. Aggregate by groups to get one vector per group, or leave grouping off to turn the whole table into a single profile. Each row can carry a weight, so a location contributes in proportion to a measure you choose instead of contributing equally.

Use it to describe an entity from its own locations, for example one vector per brand built from the embeddings of its branches and weighted by the sales of each branch. Or use it to describe a location from the places its people come from, for example one vector per store built from the residential areas of its visitors and weighted by the number of visitors from each area. The resulting profile can be compared, clustered or searched against like any other embedding.

The output keeps the input's embedding column names, types and order, so it connects directly to Similarity Search, Clustering, Mean Deviation or Change Detection.

**Inputs**

* **Embeddings table**: Table containing the location embeddings to summarize. Every numeric column other than the ID, date and weight columns is used as an embedding dimension, and non-numeric columns are ignored.

**Settings**

* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: One profile per ID, or a single profile for the whole table when grouping is off.
  * **Spatio-temporal**: One profile per ID and time period, or one per time period when grouping is off. Use it to track how a profile moves over time.
* **Aggregate by groups**: Whether to build a separate profile for each group, such as one vector per brand (default: false). When off, every row goes into a single profile and no ID column is needed.
* **ID column**: Column the embeddings are aggregated by, such as the brand of each branch or the store a visitor traveled to (shown only when Aggregate by groups is enabled). The output holds one profile per distinct value of this column.
* **Date column**: Column holding the time period of each row (shown only for Spatio-temporal analysis). The profile is built per time period, and per group as well when grouping is enabled.
* **Weight the embeddings**: Whether each embedding contributes in proportion to a weight column, instead of contributing equally (default: false).
* **Weight column**: Column holding the weight of each row, such as the number of visitors, the sales, or the population of the area (shown only when Weight the embeddings is enabled). A row with a null or zero weight does not contribute to its profile.

**Outputs**

* **Output table**: The profile table with the following columns:
  * `<id>`: The profile identifier. With Aggregate by groups enabled, it is the input ID column with its own name and values. With grouping off, it is a `geoid` column holding the constant `'profile'`, so the output always has an identifier for the next component to use.
  * `<date>`: The time period (only for Spatio-temporal analysis).
  * One column per embedding dimension, with the same name, type and order as in the input table.

{% hint style="info" %}
Each dimension of the profile is computed as `SUM(embedding * weight) / SUM(weight)`, with every weight set to 1 when you don't weight the embeddings. A row whose value for one dimension is null is left out of that dimension only.

The profile is not rescaled to length 1, because a mean of unit-length vectors is shorter than 1. Add a [Vector Normalization](#vector-normalization) component after this one when the next step uses the Dot product metric.
{% endhint %}

{% hint style="warning" %}
Every numeric column that is not the ID, the date or the weight is averaged into the profile. This includes a Quadbin index, which is stored as an integer. Drop numeric columns you don't want as dimensions before this component, or use a string index such as H3.
{% endhint %}

## Mean Deviation

**Description**

Compares each location's embedding against a mean embedding to measure how far each location sits from its baseline. The baseline is the whole dataset, a time period, or a group, so the same component ranks locations by how representative they are and flags the ones that break the pattern.

This component is particularly useful for anomaly detection, for finding regions that deviate from the overall pattern, and in time series, for spotting locations that break from the typical pattern of their period.

**Inputs**

* **Embeddings table**: Table containing the location embeddings to compare against the relevant mean.

**Settings**

* **Location ID column**: Column containing the location identifiers. This column is used to maintain the relationship between input embeddings and their scores in the output.
* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: A single mean embedding is computed across all locations, and each location is compared against it.
  * **Spatio-temporal**: Introduces a date dimension, so the comparison can account for time (see Comparison method).
* **Date column**: Column containing the dates of the embeddings (shown only for Spatio-temporal analysis).
* **Comparison method**: Determines how each location and time period is compared against the mean (shown only for Spatio-temporal analysis, default: Time-aligned).
  * **Time-aligned**: Compares each location against the mean embedding of the same time period. This highlights locations that deviate from the typical pattern at their own point in time.
  * **Cross-temporal**: Compares each location against the mean embedding across all time periods. This highlights deviation from the long-run average.
* **Compare within groups**: Whether to compare each location against the mean of its own group rather than the mean across all groups (default: false). This is useful when the dataset contains distinct populations, such as land cover classes, regions or clusters, and you want anomalies relative to each population.
* **Group column**: Column defining the groups (shown only when Compare within groups is enabled). With Time-aligned analysis the mean is computed per time period and group, and with Cross-temporal analysis per group across all periods. The column is only used to partition the data and is not included in the output.
* **Distance metric**: Distance function used to compare each embedding to the mean, either **Cosine** or **Dot product** (default: Cosine). See [Cosine and Dot product](#cosine-and-dot-product) to choose between them. The component rescales the mean embedding to length 1 itself, so Dot product only requires your input embeddings to have length 1.

**Outputs**

* **Output table**: The mean deviation table with the following columns, ordered by `mean_deviation` from highest to lowest:
  * `<id>`: Identifier of the location.
  * `<date>`: The time period of the observation (only for Spatio-temporal analysis).
  * `distance`: Distance between the location's embedding and the relevant mean embedding, from 0 to 2.
  * `mean_deviation`: The same distance rescaled from 0 to 1, as `distance / 2`. 0 means the location points in the same direction as its mean, 0.5 that it is orthogonal to it, and 1 that it points in the opposite direction.

{% hint style="info" %}
Spatio-temporal analysis doesn't require every location to have a value for every period. A location missing from a period is left out of that period's mean and produces no row for it.
{% endhint %}

## Neighborhood Deviation

**Description**

For each grid cell, measures how much its embedding differs from the embeddings of its neighbors on an H3 or Quadbin grid, as the mean dissimilarity across its k-ring. High values mark boundaries and gradients in the embedding field.

The output is a natural input to a [Getis Ord](/carto-user-manual/workflows/components/statistics.md#getis-ord) or [Hotspot Analysis](/carto-user-manual/workflows/components/statistics.md#hotspot-analysis) component, to find where those changes cluster significantly.

**Inputs**

* **Embeddings table**: Table containing grid-indexed embeddings. Every numeric column other than the index column, and the date column for spatio-temporal analysis, is used as an embedding dimension.

**Settings**

* **Index column**: The H3 or Quadbin index identifying each cell. The grid type is detected automatically from the column.
* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: Compares each cell to its neighbors.
  * **Spatio-temporal**: Compares each cell only to its neighbors in the same time period, and the output carries the time dimension.
* **Date column**: Column holding the time period of each cell (shown only for Spatio-temporal analysis).
* **Size**: How many rings of neighbors around each cell to include (1-10, default: 1). One ring is the 6 cells touching a cell on H3, or the 8 on Quadbin. Each extra ring widens the neighborhood and smooths the result, so ring 1 localizes a boundary most sharply.
* **Kernel function for spatial weights**: How to weight neighbors by their ring distance (default: uniform). **uniform** weights every ring equally, while **triangular**, **quadratic**, **quartic** and **gaussian** give nearer rings more weight. Every kernel covers the same rings, so the kernel only changes how much each ring counts, never which cells take part.
* **Distance metric**: Distance function used to compare embeddings, either **Cosine** or **Dot product** (default: Cosine). See [Cosine and Dot product](#cosine-and-dot-product) to choose between them.

**Outputs**

* **Output table**: One row per cell, or per cell and time period for spatio-temporal analysis, with the following columns:
  * `<index>`: The grid index.
  * `<date>`: The time period of the cell (only for Spatio-temporal analysis).
  * `distance`: The kernel-weighted mean dissimilarity between the cell and its neighbors, from 0 to 2.
  * `neighbor_deviation`: The same value rescaled from 0 to 1, as `distance / 2`. Higher values mean the cell differs more from its surroundings.

{% hint style="info" %}
A cell needs at least one neighbor in the table to produce a value. Cells with no neighbors in range are left out of the output.
{% endhint %}

## Similarity Search

**Description**

Identifies regions with comparable spatial or contextual characteristics by leveraging spatially aware embeddings. It compares the embeddings of one or more reference locations against a set of search location embeddings to identify areas that share similar spatial patterns or features. This component supports any embedding representation that encodes spatial relationships and can be applied across a wide range of domains, including remote sensing, environmental monitoring, and spatial data analysis.

This component is particularly useful for finding locations with similar characteristics, identifying patterns across different regions, discovering areas that match specific reference conditions, and conducting spatial similarity analysis at scale.

**Inputs**

* **Search locations**: Table containing vectors for which similarity to the reference set will be computed.
* **Reference location(s)**: Table containing vector(s) representing the baseline data or items to compare against.

**Settings**

* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: Compares embeddings without temporal considerations.
  * **Spatio-temporal**: Each embedding has a date, and the comparison accounts for time (see Comparison method).
* **Search ID column**: Column containing the IDs of the search vectors. This column is used to maintain the relationship between input embeddings and their similarity scores in the output.
* **Search date column**: Column containing the dates of the search embeddings (shown only for Spatio-temporal analysis).
* **Reference ID column**: Column containing the IDs of the reference vector(s). This column is used to maintain the relationship between input embeddings and their similarity scores in the output.
* **Reference date column**: Column containing the dates of the reference embeddings (shown only for Spatio-temporal analysis).
* **Comparison method**: Determines how locations are compared across time periods (shown only for Spatio-temporal analysis, default: Time-aligned).
  * **Time-aligned**: Compares each reference location only to the search locations in the same time period.
  * **Cross-temporal**: Compares each reference location against the search locations in every time period.
* **Distance metric**: Distance function used to compare vectors, either **Cosine** or **Dot product** (default: Cosine). See [Cosine and Dot product](#cosine-and-dot-product) to choose between them.
* **Aggregate across reference locations**: Whether the similarity results from multiple reference locations should be aggregated into a single output (default: true). When enabled, the component computes similarity maps for each reference location and returns their mean or maximum, producing one consolidated similarity result.
* **Aggregate function**: The function to use when aggregating similarity results from multiple reference locations (default: AVG).
  * **AVG**: Returns the average similarity score across all reference locations.
  * **MAX**: Returns the maximum similarity score across all reference locations.
* **Return top-k similar locations**: Whether to return only the top-k most similar locations (default: true). When enabled, only the most similar locations are returned, improving performance and focusing on the most relevant results.
* **Top-k metric**: Number of most similar locations to return (1-infinity, default: 10). When aggregating across reference locations, it returns the top-k aggregated results, and otherwise the top-k for each reference location.
* **Create vector index**: Whether to create a vector index to optimize the similarity search at scale (default: false, advanced option). Only available on **BigQuery** connections. When enabled, uses Approximate Nearest Neighbor search to improve performance with the trade-off of returning more approximate results. Without a vector index, uses brute force search to measure distance for every record.

**Outputs**

* **Output table**: The similarity table with the following columns:
  * `reference_<id>`: Identifier of the reference location. When aggregating across reference locations, it holds the list of all reference locations.
  * `reference_<date>`: Date of the reference embedding (only for Spatio-temporal analysis).
  * `search_<id>`: Identifier of the search location.
  * `search_<date>`: Date of the search embedding (only for Spatio-temporal analysis).
  * `distance`: Distance between the reference and search embeddings.
  * `similarity_score`: Similarity between the reference and search embeddings, where higher values indicate greater similarity. On BigQuery it is computed as `1 - distance / 2`, giving 0 for opposite vectors, 0.5 for orthogonal ones and 1 for identical ones.

{% hint style="info" %}
**On Snowflake**, the **Distance metric** offers **Cosine** and **Euclidean**. With Euclidean, the similarity score compares each search location's distance to the reference against its distance to the mean vector of the data, and is positive only when the search location is more similar to the reference than the mean is. Two more settings reduce the dimensionality of the embeddings with Principal Component Analysis (PCA) before the comparison: **Reduce embedding dimensionality** (default: false) and **PCA explained variance**, the share of the original variance to preserve (0.01-0.99, default: 0.9). The component also returns a **Metrics table** with `total_explained_variance_ratio` and `number_of_principal_components`.
{% endhint %}

{% hint style="info" %}
The component requires that both reference and search tables contain compatible embedding vectors with the same dimensionality. The similarity calculation will be performed for all combinations of reference and search locations, or for the top-k most similar pairs when the top-k option is enabled.
{% endhint %}

## Spatial Aggregation

**Description**

Moves embeddings from one geometry set to another. For every target polygon, it aggregates the embedding dimensions of all the source features that overlap it, weighted by the overlapping area. Use it to take fine-grained embeddings up to the polygons you work with, such as census tracts, neighborhoods, or your own sales territories.

**Inputs**

* **Source embedding table**: Table containing the embeddings to aggregate, with a geometry column. Every numeric column other than the geometry column, and the date column for spatio-temporal analysis, is used as an embedding dimension.
* **Target polygon table**: The polygons to enrich with the aggregated embedding dimensions.

**Settings**

* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: Aggregates all the source embeddings into each target polygon.
  * **Spatio-temporal**: Aggregates the source embeddings per time period, and the output carries the time dimension.
* **Source geometry column**: Geography column of the source embeddings. Source features should be polygons, because the weights are areas and a point has none.
* **Target ID column**: Column uniquely identifying each target polygon.
* **Target geometry column**: Geography column of the target polygons. It is carried through to the output, so the result can be mapped directly.
* **Source date column**: Column holding the time period of the source embeddings (shown only for Spatio-temporal analysis).
* **Aggregation methods**: One or more statistics to compute for each embedding dimension (default: Mean). Each source feature is weighted by the area of it that falls inside the target polygon.
  * **Mean**: Area-weighted mean across the overlapping source features.
  * **Max**: Maximum value across the overlapping source features.
  * **Min**: Minimum value across the overlapping source features.
  * **Standard deviation**: Area-weighted standard deviation across the overlapping source features. It is 0 when a single source feature overlaps the target polygon.
  * **Dominant**: The values of the single source feature with the largest overlap with the target polygon.

**Outputs**

* **Output table**: The target polygons enriched with the aggregated embeddings, with the following columns:
  * `<target_id>`: Identifier of the target polygon.
  * `<target_geom>`: Geometry of the target polygon.
  * `<date>`: The time period (only for Spatio-temporal analysis).
  * One column per embedding dimension and selected method, named with the method as a suffix (`_mean`, `_max`, `_min`, `_std` and `_dominant`). Columns are grouped by method in that order, and keep the order of the source table within each method.

{% hint style="info" %}
Target polygons that no source feature overlaps are left out of the output.

The other components in this extension package use every numeric column as an embedding dimension. When the output feeds one of them, select a single aggregation method, or keep only the columns of one method. An area-weighted mean of unit-length vectors is shorter than 1, so add a [Vector Normalization](#vector-normalization) component on the Mean output before using the Dot product metric.
{% endhint %}

## Vector Normalization

**Description**

Rescales every embedding vector to length 1, dividing each dimension by the vector's own length. The direction of every vector is preserved exactly, and only its magnitude changes.

Unit-length embeddings make the Dot product metric in the other components return the same values as Cosine at a lower cost, so normalizing once on your source table makes every later comparison cheaper. Aggregating breaks unit length, because a mean of unit vectors is shorter than 1. Place this component after [Spatial Aggregation](#spatial-aggregation) or [Embedding Profile](#embedding-profile) when the next step uses Dot product. Learn more in [Cosine and Dot product](#cosine-and-dot-product).

**Inputs**

* **Embeddings table**: Table containing the embeddings. Every numeric column other than the identifier column, and the date column for spatio-temporal analysis, is used as an embedding dimension.

**Settings**

* **Identifier column**: Column identifying each row. It is carried through to the output unchanged and never treated as an embedding dimension.
* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial). Each row is rescaled on its own, so this setting only exists to declare the date column.
* **Date column**: Column holding the time period of each row (shown only for Spatio-temporal analysis). It is carried through unchanged. Set it whenever your period column is numeric, because an undeclared numeric column is treated as an embedding dimension and rescaled.

**Outputs**

* **Output table**: One row per input row, with the same column names and order, and every embedding vector rescaled to length 1. The output adds no column for the original length, because the next component would read it as an embedding dimension.

{% hint style="info" %}
An all-zero vector has no direction to preserve, so its dimensions are returned as `NULL`. Filter out zero vectors before comparing the output with another component.

Don't normalize the Standard deviation output of [Spatial Aggregation](#spatial-aggregation): its magnitude is the only thing it measures. Normalize the Mean output instead.
{% endhint %}

## Visualization

**Description**

Transforms high-dimensional embeddings into colors for intuitive visualization. It supports two dimensionality reduction approaches: Principal Component Analysis (PCA) for automatic feature extraction, or manual selection of specific embedding dimensions. On BigQuery, it also supports two color mappings: RGB, which maps three components to the red, green and blue channels, and Bivariate, which crosses two components into a 9-class bivariate map.

This component is particularly useful for creating visual representations of spatial patterns, identifying clusters through color similarity, and generating color-coded maps that reveal underlying data structures in your embeddings.

**Inputs**

* **Embedding table**: Table containing the embeddings to visualize. With the Manual reduction technique, only the columns you pick as channels or axes are read.

**Settings**

* **ID column**: Column containing unique identifiers for each embedding. This column is used to maintain the relationship between input embeddings and their color assignments in the output.
* **Analysis type**: Determines whether the analysis is spatial or spatio-temporal (default: Spatial).
  * **Spatial**: Analyzes embeddings at a single point in time or without temporal considerations. Use this for static spatial pattern visualization.
  * **Spatio-temporal**: Analyzes embeddings across multiple time periods, enabling visualization of temporal changes in spatial patterns. Requires a date column to be specified.
* **Date column**: Column containing temporal information for spatio-temporal analysis (required when Analysis type is Spatio-temporal). This column should contain date, datetime, timestamp, or numeric time values that identify when each embedding was captured.
* **Dimensionality reduction technique**: Method for reducing the embeddings to the components used for visualization (default: PCA).
  * **PCA**: Automatically extracts the most significant principal components from your embeddings, three for RGB and two for Bivariate. This approach preserves the maximum variance in your data and is ideal when you want to discover the most important patterns automatically.
  * **Manual**: Allows you to select specific embedding dimensions to use as components. Use this when you have domain knowledge about which features are most important for your visualization.
* **Color mapping**: How the reduced components are mapped to colors (default: RGB). Only available on **BigQuery** connections, as Snowflake always uses RGB.
  * **RGB**: Maps three components to the red, green and blue channels, producing a continuous color for each location.
  * **Bivariate**: Cuts two components into terciles (low, medium and high) and crosses them into a 9-class bivariate map.
* **Red channel**, **Green channel** and **Blue channel**: Columns controlling the intensity of each color channel (required when using the Manual reduction technique with RGB color mapping).
* **First axis** and **Second axis**: Columns mapped to the two axes of the bivariate map (required when using the Manual reduction technique with Bivariate color mapping).

**Outputs**

* **Output table**: The image table. With RGB color mapping, it has the following columns:

  * `<geoid>`: Original identifier for each embedding.
  * `<date>`: The time period of the observation (only for Spatio-temporal analysis).
  * `r_channel`, `g_channel` and `b_channel`: Red, green and blue channel values (0-255). Each channel is scaled across the whole table, so 0 is the lowest value of that component anywhere in the input and 255 the highest.
  * `hex_color`: Hexadecimal color representation (e.g., #FF5733) for easy use in mapping applications.

  With Bivariate color mapping, it has the following columns:

  * `<geoid>`: Original identifier for each embedding.
  * `<date>`: The time period of the observation (only for Spatio-temporal analysis).
  * `component_1` and `component_2`: Values of the two components.
  * `class_1` and `class_2`: Tercile of each component (1 = low, 2 = medium, 3 = high).
  * `bivariate_class`: Label combining the two terciles, from `Low - Low` to `High - High`.
  * `hex_color`: Hexadecimal color for each bivariate class, from light gray for `Low - Low` to dark blue for `High - High`.
* **Metrics table**: The metrics table with the following columns:
  * `total_explained_variance_ratio`: The proportion of variance in the original data that is explained by the dimensionality reduction. When using PCA, this indicates how much information is preserved in the visualization. Values closer to 1.0 indicate that the visualization captures most of the original data's structure.
  * `luminance_variance`: The variance of the luminance values across all visualized embeddings, for the RGB color mapping. Luminance is calculated using the standard RGB-to-luminance conversion formula (0.2989xR + 0.5870xG + 0.1140xB) and represents the perceived brightness of each color. Higher variance indicates greater diversity in brightness levels across your visualization, while lower variance suggests more uniform brightness distribution.

{% hint style="info" %}
In spatio-temporal analysis, colors are computed across all time periods at once, so every period shares the same legend and a location that changes color between periods reflects a real change in its embedding.
{% endhint %}

{% hint style="warning" %}
Spatio-temporal analysis requires every ID to have a value for every date. If any is missing, the run fails with `Validation failed: Not every geoid has values for each date`. Fill or drop the incomplete IDs before running the component.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.carto.com/carto-user-manual/workflows/components/embedding-analytics.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
