Skip to content

CountEmbedder

srai.embedders.CountEmbedder(
    expected_output_features=None, count_subcategories=True
)

Bases: Embedder

Simple Embedder that counts occurences of feature values.

PARAMETER DESCRIPTION
count_subcategories

Whether to count all subcategories individually or count features only on the highest level based on features column name. Defaults to True.

TYPE: bool DEFAULT: True

Source code in srai/embedders/count_embedder.py
def __init__(
    self,
    expected_output_features: Optional[
        Union[list[str], OsmTagsFilter, GroupedOsmTagsFilter]
    ] = None,
    count_subcategories: bool = True,
) -> None:
    """
    Init CountEmbedder.

    Args:
        expected_output_features
            (Union[List[str], OsmTagsFilter, GroupedOsmTagsFilter], optional):
            The features that are expected to be found in the resulting embedding.
            If not None, the missing features are added and filled with 0.
            The unexpected features are removed. The resulting columns are sorted accordingly.
            Defaults to None.
        count_subcategories (bool, optional): Whether to count all subcategories individually
            or count features only on the highest level based on features column name.
            Defaults to True.
    """
    self.count_subcategories = count_subcategories
    self._parse_expected_output_features(expected_output_features)

transform(regions_gdf, features_gdf, joint_gdf)

Embed a given GeoDataFrame.

Creates region embeddings by counting the frequencies of each feature value. Expects features_gdf to be in wide format with each column being a separate type of feature (e.g. amenity, leisure) and rows to hold values of these features for each object. The resulting DataFrame will have columns made by combining the feature name (column) and value (row) e.g. amenity_fuel or type_0. The rows will hold numbers of this type of feature in each region.

PARAMETER DESCRIPTION
regions_gdf

Region indexes and geometries.

TYPE: gpd.GeoDataFrame

features_gdf

Feature indexes, geometries and feature values.

TYPE: gpd.GeoDataFrame

joint_gdf

Joiner result with region-feature multi-index.

TYPE: gpd.GeoDataFrame

RETURNS DESCRIPTION
pd.DataFrame

pd.DataFrame: Embedding for each region in regions_gdf.

RAISES DESCRIPTION
ValueError

If features_gdf is empty and self.expected_output_features is not set.

ValueError

If any of the gdfs index names is None.

ValueError

If joint_gdf.index is not of type pd.MultiIndex or doesn't have 2 levels.

ValueError

If index levels in gdfs don't overlap correctly.

Source code in srai/embedders/count_embedder.py
def transform(
    self,
    regions_gdf: gpd.GeoDataFrame,
    features_gdf: gpd.GeoDataFrame,
    joint_gdf: gpd.GeoDataFrame,
) -> pd.DataFrame:
    """
    Embed a given GeoDataFrame.

    Creates region embeddings by counting the frequencies of each feature value.
    Expects features_gdf to be in wide format with each column
    being a separate type of feature (e.g. amenity, leisure)
    and rows to hold values of these features for each object.
    The resulting DataFrame will have columns made by combining
    the feature name (column) and value (row) e.g. amenity_fuel or type_0.
    The rows will hold numbers of this type of feature in each region.

    Args:
        regions_gdf (gpd.GeoDataFrame): Region indexes and geometries.
        features_gdf (gpd.GeoDataFrame): Feature indexes, geometries and feature values.
        joint_gdf (gpd.GeoDataFrame): Joiner result with region-feature multi-index.

    Returns:
        pd.DataFrame: Embedding for each region in regions_gdf.

    Raises:
        ValueError: If features_gdf is empty and self.expected_output_features is not set.
        ValueError: If any of the gdfs index names is None.
        ValueError: If joint_gdf.index is not of type pd.MultiIndex or doesn't have 2 levels.
        ValueError: If index levels in gdfs don't overlap correctly.
    """
    self._validate_indexes(regions_gdf, features_gdf, joint_gdf)
    if features_gdf.empty:
        if self.expected_output_features is not None:
            return pd.DataFrame(
                0, index=regions_gdf.index, columns=self.expected_output_features
            )
        else:
            raise ValueError(
                "Cannot embed with empty features_gdf and no expected_output_features."
            )

    regions_df = self._remove_geometry_if_present(regions_gdf)
    features_df = self._remove_geometry_if_present(features_gdf)
    joint_df = self._remove_geometry_if_present(joint_gdf)

    if self.count_subcategories:
        feature_encodings = pd.get_dummies(features_df)
    else:
        feature_encodings = features_df.notna().astype(int)
    joint_with_encodings = joint_df.join(feature_encodings)
    region_embeddings = joint_with_encodings.groupby(level=0).sum()

    region_embeddings = self._maybe_filter_to_expected_features(region_embeddings)
    region_embedding_df = regions_df.join(region_embeddings, how="left").fillna(0).astype(int)

    return region_embedding_df