Repository: holoviz/holoviews
Pull request #6519 (2025-02-21 17:30:17)

fix: regression in get_value_array
Fixes https://github.com/holoviz/holoviews/issues/6516

The performance improvement done in https://github.com/holoviz/holoviews/pull/6470 introduced a bug. The bug came when trying to bypass the for loop, which was done with a `.unique` call of the dataset. This bug caused the following regression. In short, when using dim-expression, the sensor's output would now be two-sized lengths instead of three-sized lengths like the rest of the data, resulting in an error when converting to Bokeh valid data.  

This PR replaces the unique call with a conversion to a numpy array, keeping the data size. 


``` python
import geopandas as gpd
import geoviews as gv
import pandas as pd

import holoviews as hv

hv.extension("bokeh")

df = pd.DataFrame(
    {"Longitude": [0, 1, 2], "Latitude": [0, 1, 2], "Sensor": ["S1", "S2", "S1"]}
)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df["Longitude"], df["Latitude"]))

gv.Points(gdf).opts(line_color=hv.dim("Sensor").categorize(["red", "blue", "yellow"]))

```


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/holoviz/holoviews/pull/6519?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=holoviz) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 88.79%. Comparing base [(`d3a19e4`)](https://app.codecov.io/gh/holoviz/holoviews/commit/d3a19e495aada80cd6039d5fd5bfceab08cd0e1e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=holoviz) to head [(`98f150f`)](https://app.codecov.io/gh/holoviz/holoviews/commit/98f150f06ff503a65db6f39d8db319c353567bc2?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=holoviz).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #6519      +/-   ##
==========================================
- Coverage   88.79%   88.79%   -0.01%     
==========================================
  Files         323      323              
  Lines       68940    68939       -1     
==========================================
- Hits        61216    61213       -3     
- Misses       7724     7726       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/holoviz/holoviews/pull/6519?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=holoviz).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=holoviz).


Patch:
diff --git a/holoviews/core/data/spatialpandas.py b/holoviews/core/data/spatialpandas.py
index c081a94a7..5fc63901e 100644
--- a/holoviews/core/data/spatialpandas.py
+++ b/holoviews/core/data/spatialpandas.py
@@ -643,9 +643,7 @@ def get_value_array(data, dimension, expanded, keep_index, geom_col,
     is_scalars = [isscalar(value) for value in column]
     all_scalar = all(is_scalars)
     if all_scalar and not expanded:
-        scal_unique = column.unique()
-        # .unique() on categorical dtype doesn't return a np array
-        return scal_unique if isinstance(scal_unique, np.ndarray) else scal_unique.to_numpy()
+        return np.asarray(column)
     arrays, scalars = [], []
     for i, geom in enumerate(data[geom_col]):
         val = column.iloc[i]
diff --git a/pixi.toml b/pixi.toml
index 4cd02a3ba..c1ba8fbb4 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -133,7 +133,6 @@ spatialpandas = "*"
 streamz = ">=0.5.0"
 xarray = ">=0.10.4"
 xyzservices = "*"
-libsqlite = "!=3.49.*" # 2025-02; Breaks ibis tests, https://github.com/ibis-project/ibis/issues/10865 (remove dependency after problem is solved)
 
 [feature.optional.target.unix.dependencies]
 tsdownsample = "*" # currently not available on Windows


Test patch:
diff --git a/holoviews/tests/core/data/test_spatialpandas.py b/holoviews/tests/core/data/test_spatialpandas.py
index d020b5c1a..037973e8a 100644
--- a/holoviews/tests/core/data/test_spatialpandas.py
+++ b/holoviews/tests/core/data/test_spatialpandas.py
@@ -4,6 +4,7 @@ Tests for the spatialpandas interface.
 from unittest import SkipTest
 
 import numpy as np
+import pandas as pd
 
 try:
     import spatialpandas
@@ -24,12 +25,14 @@ try:
 except ImportError:
     dd = None
 
+from holoviews import Dimension
 from holoviews.core.data import (
     DaskSpatialPandasInterface,
     Dataset,
     SpatialPandasInterface,
 )
 from holoviews.core.data.interface import DataError
+from holoviews.core.data.spatialpandas import get_value_array
 from holoviews.element import Path, Points, Polygons
 from holoviews.element.comparison import ComparisonTestCase
 
@@ -301,3 +304,14 @@ class DaskSpatialPandasTest(GeomTests, RoundTripTests):
 
     def test_sort_by_value(self):
         raise SkipTest("Not supported")
+
+
+
+def test_regression_get_value_array():
+    # See: https://github.com/holoviz/holoviews/pull/6519
+    df = pd.DataFrame(
+        {"Longitude": [0, 1, 2], "Latitude": [0, 1, 2], "Sensor": ["S1", "S2", "S1"]}
+    )
+    result = get_value_array(df, Dimension("Sensor"), False, None, None, None)
+
+    np.testing.assert_array_equal(df.Sensor, result)