Skip to content

Commit 21c1796

Browse files
committed
perf(datashader): factorize instead of np.unique for hex alpha-strip
The per-point color vector alpha-strip used np.unique(return_inverse=True), which sorts millions of strings (argsort dominated the datashader render: ~1s at 10M). pd.factorize dedups in O(n) via hashing with no sort and produces a byte-identical per-point result. Modest win for the no-color/categorical paths.
1 parent cdaa0c2 commit 21c1796

1 file changed

Lines changed: 4 additions & 3 deletions

File tree

src/spatialdata_plot/pl/_datashader.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,10 @@ def _shade_datashader_aggregate(
382382
and color_vector[0].startswith("#")
383383
):
384384
# color_vector usually holds only a few distinct hex strings (one per category), so strip
385-
# alpha on the unique values and map back rather than parsing once per point.
386-
unique_hex, inverse = np.unique(color_vector, return_inverse=True)
387-
color_vector = np.asarray([_hex_no_alpha(c) for c in unique_hex])[inverse]
385+
# alpha on the unique values and map back rather than parsing once per point. pd.factorize
386+
# dedups in O(n) (hash, no sort) — np.unique would sort millions of strings (argsort cost).
387+
codes, uniques = pd.factorize(np.asarray(color_vector))
388+
color_vector = np.asarray([_hex_no_alpha(c) for c in uniques])[codes]
388389

389390
# density without a color column collapses to a sequential count gradient; everything else with no
390391
# explicit continuous value (categorical or no color) goes through the categorical shader.

0 commit comments

Comments
 (0)