Skip to content

feat(python/sedonadb-geopandas): add dissolve - #1246

Open
jiayuasu wants to merge 3 commits into
apache:mainfrom
jiayuasu:feature/geopandas-dissolve
Open

feat(python/sedonadb-geopandas): add dissolve#1246
jiayuasu wants to merge 3 commits into
apache:mainfrom
jiayuasu:feature/geopandas-dissolve

Conversation

@jiayuasu

@jiayuasu jiayuasu commented Sep 9, 2026

Copy link
Copy Markdown
Member

What changes

Second slice of the series that started with #1195 (column assignment). This one adds GeoDataFrame.dissolve() to the experimental sedonadb-geopandas package: group rows on one or more key columns (or on nothing, to dissolve everything into one row) and union each group's geometry.

  • Geometry aggregation goes through ST_Collect_Agg followed by a ST_UnaryUnion in a separate projection. ST_Union_Agg only initializes for polygonal input (ST_Union_Agg returns NULL for point inputs #1093), so a group of points or lines would dissolve to NULL; collect-then-union is geometry-general and yields the geometry types GeoPandas yields. The union sits in its own projection because a scalar function wrapped around an aggregate is not a valid aggregate expression. A group whose geometries are all null coalesces to an empty geometry collection re-typed back to geometry, matching GeoPandas.
  • Missing keys follow pandas: IEEE NaN in a floating-point key is normalized to null before grouping, in both dropna modes, so a column holding both representations forms one missing group rather than two (and dropna=True drops both). Floating-ness is decided from the Arrow type, dictionary encoding unwrapped, rather than from the type's string form, so a list<double> column is not mistaken for something isnan() can be applied to.
  • Validation matches GeoPandas: by=[] raises (unlike by=None), unknown keys raise KeyError, and only aggfunc="first" is supported for now with an error that points at the SedonaDB DataFrame API for anything else.
  • Temporal group keys are rejected for now. Numpy-backed pandas delivers a missing timestamp or duration as an INT64_MIN tick, which must group (and dropna) as missing rather than as a value; that handling arrives with the temporal follow-up.

Documented differences from GeoPandas (also in the README): group keys stay ordinary columns rather than becoming the index; "first" is an unordered aggregate that does not skip missing values; dissolving an empty frame without keys yields one row rather than zero; a group mixing 2D and 3D geometries raises rather than being promoted to 3D; and grouping is observed-only for categorical keys, since the category domain does not survive a relational aggregation.

Testing

18 new tests (136 in the package), including a corpus over every geometry type, GeoPandas parity for dropna, nested-float and dictionary-encoded keys, the all-null group, and the categorical case; run with warnings promoted to errors against both a source-built current main and the released sedonadb 0.4.1 in a clean environment (pandas 2 and 3). Ruff lint/format clean.

Group rows on one or more key columns and union each group's geometry
via collect_agg plus unary_union — ST_Union_Agg only initializes for
polygonal input (apache#1093) — with the union in a separate projection since
a scalar wrapped around an aggregate is not a valid aggregate
expression. dropna matches GeoPandas by treating IEEE NaN in floating
keys as missing alongside SQL null, with dictionary encoding unwrapped;
an all-null geometry group coalesces to an empty geometry collection
re-typed back to geometry. Documented differences: group keys stay
ordinary columns (no index), first is unordered and does not skip
missing values, an empty frame without keys yields one row, mixed 2D/3D
groups raise, and grouping is observed-only. Temporal group keys are
rejected for now: pandas missing values arrive from numpy-backed frames
as a sentinel tick that must group as missing, which needs the dedicated
temporal handling that arrives as its own change.
@jiayuasu
jiayuasu marked this pull request as draft September 9, 2026 06:57
…ther in both modes

Missing-key handling only ran with dropna=True, so with dropna=False a
SQL NULL and an IEEE NaN in the same floating-point key column formed
two missing groups where pandas forms one. Normalize NaN to null before
grouping, in both modes, so the two representations group as a single
missing key; the dropna filter then only needs the null check.
…olumn named self

Build the NaN-to-null gate in the key's own float type so a Float32
key is not widened by the addition, and pass every mutate() column as
a positional alias rather than a keyword: a column named 'self'
collided with mutate's own first parameter in assignment,
reprojection, and dissolve alike.
@jiayuasu
jiayuasu requested a review from paleolimbot September 9, 2026 07:55
@jiayuasu
jiayuasu marked this pull request as ready for review September 9, 2026 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant