Skip to content

Support string/categorical columns in rasterize with QGIS-visible category labels #3482

Description

@brendancol

Reason or Problem

rasterize only accepts numeric columns. _parse_input calls .astype(np.float64) on the chosen column, so passing a string or categorical field (land-cover classes, zoning codes, and similar) raises ValueError: could not convert string to float. Users with text-keyed vector data have to hand-encode their categories to integers before rasterizing, then keep a separate lookup table to remember which integer meant what. That mapping is lost once the raster is written to disk, so opening the result in QGIS shows bare numbers instead of class names.

Proposal

Accept a string or categorical column in rasterize, encode the labels to integer codes, and carry the value-to-label mapping in the output attrs so it can be written to a GeoTIFF and shown in QGIS.

Design:

  • Encoding: when the selected column has a non-numeric dtype (object/string/CategoricalDtype), encode it with pandas Categorical. Already-categorical columns keep their declared category order; plain string/object columns get the pandas default (lexically sorted). Pixel values are the integer codes 0..N-1; missing values use the pandas -1 sentinel.
  • Output: default to int32 with nodata -1 when a categorical column is detected and the caller did not pass dtype/fill. Numeric columns and (geometry, value) pairs keep their current float64/NaN behavior.
  • Attrs: store category_names (ordered list of labels, index = pixel value) and an auto-generated category_colors (one distinct RGBA per category, from an evenly spaced HSV spread).
  • GeoTIFF interop: to_geotiff writes a PAM <file>.tif.aux.xml sidecar containing <CategoryNames> and a thematic <GDALRasterAttributeTable> (Value/Class plus Red/Green/Blue/Alpha columns). This is the only mechanism GDAL/QGIS reads for category labels. An embedded RAT in the GeoTIFF GDAL_METADATA tag is ignored by GDAL (confirmed with gdalinfo 3.10.3), while the sidecar is read back as Categories: and a full RAT. open_geotiff parses the sidecar back into attrs for a round-trip.

Usage:

import geopandas as gpd
from shapely.geometry import box
from xrspatial import rasterize
from xrspatial.geotiff import to_geotiff

gdf = gpd.GeoDataFrame(
    {'landcover': ['water', 'forest', 'urban']},
    geometry=[box(0, 0, 5, 5), box(5, 0, 10, 5), box(0, 5, 5, 10)],
    crs='EPSG:4326',
)
result = rasterize(gdf, column='landcover', width=100, height=100)
# result is int32, pixels are 0/1/2, nodata -1
# result.attrs['category_names'] == ['forest', 'urban', 'water']
to_geotiff(result, 'landcover.tif')   # also writes landcover.tif.aux.xml

Opening landcover.tif in QGIS shows the class names instead of the raw codes.

Value: Rasterizing thematic vector data becomes a single call with no manual encoding or external lookup table, and the labels travel with the file into any GDAL-based tool.

Stakeholders and Impacts

Anyone rasterizing categorical vector data. Touches rasterize (_parse_input, dtype/fill defaults, attrs) and the GeoTIFF reader/writer (new sidecar helper, to_geotiff write hook, open_geotiff read, attrs contract). The .xrs accessor needs no change since it forwards kwargs. Encoding happens before backend dispatch, so all four backends are covered.

Drawbacks

Writing a GeoTIFF now produces a second file (the .aux.xml sidecar) when categories are present. This is the standard GDAL PAM convention, but it is an extra artifact to keep alongside the .tif.

Alternatives

  • Embed the RAT/category names in the GeoTIFF GDAL_METADATA tag (no sidecar). Rejected: GDAL does not read it back, so QGIS would still show bare numbers.
  • Write a TIFF ColorMap tag for colors. Not valid for an int32 band (that tag is limited to <=16-bit palette images), so colors go in the RAT instead.

Additional Notes or Context

GDAL RAT field usage codes used: Value=MinMax(5), Class=Name(2), Red/Green/Blue/Alpha=6/7/8/9. Field types: Integer=0, String=2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAPI design and consistencyarea:vectorArea: vectorenhancementNew feature or requestgeotiffGeoTIFF module

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions