Describe the bug
Narwhals maps pandas sparse columns to Unknown in schema inference, even though those columns have clear underlying dtypes (for example Sparse[int64, 0], Sparse[float64, 0.0], Sparse[bool, False]).
This appears inconsistent with documentation that says the pandas API is fully supported.
Steps or code to reproduce the bug
#!/usr/bin/env python3
import numpy as np
import pandas as pd
import narwhals as nw
rng = np.random.default_rng(0)
df_sparse = pd.DataFrame(
{
"A": pd.arrays.SparseArray(rng.permutation([0, 1, 2] * 10)),
"B": pd.arrays.SparseArray(rng.permutation([0.0, 0.1, 0.2, -0.1, 0.2] * 6)),
"C": pd.arrays.SparseArray(rng.permutation([True, False] * 15)),
}
)
df_dense = df_sparse.sparse.to_dense()
sparse_schema = nw.from_native(df_sparse).schema
dense_schema = nw.from_native(df_dense).schema
print("sparse schema:", sparse_schema)
print("dense schema:", dense_schema)
# These operations still execute and produce the same values as the dense frame.
selected_sparse = nw.from_native(df_sparse).select("A", "B").to_native().sparse.to_dense()
selected_dense = nw.from_native(df_dense).select("A", "B").to_native()
print("select(A, B) matches dense output:", selected_sparse.equals(selected_dense))
filtered_sparse = nw.from_native(df_sparse).filter(nw.col("A") > 0).to_native().sparse.to_dense()
filtered_dense = nw.from_native(df_dense).filter(nw.col("A") > 0).to_native()
print("filter(A > 0) matches dense output:", filtered_sparse.equals(filtered_dense))
with_columns_sparse = nw.from_native(df_sparse).with_columns(double_A=nw.col("A") * 2).to_native().sparse.to_dense()
with_columns_dense = nw.from_native(df_dense).with_columns(double_A=nw.col("A") * 2).to_native()
print("with_columns(double_A) matches dense output:", with_columns_sparse.equals(with_columns_dense))
Expected results
Narwhals should infer typed columns for pandas sparse arrays (for example Int64, Float64, Boolean) instead of Unknown.
Actual results
sparse schema: Schema({'A': Unknown, 'B': Unknown, 'C': Unknown})
dense schema: Schema({'A': Int64, 'B': Float64, 'C': Boolean})
select(A, B) matches dense output: True
filter(A > 0) matches dense output: True
with_columns(double_A) matches dense output: True
Please run narwhals.show_versions() and enter the output below.
System:
python: 3.13.13 | packaged by Anaconda, Inc. | (main, Apr 14 2026, 06:14:06) [Clang 20.1.8 ]
executable: /Users/pnl0vq13/miniconda3/envs/lightgbm-dev/bin/python
machine: macOS-26.5.1-arm64-arm-64bit-Mach-O
Python dependencies:
narwhals: 2.22.1
numpy: 2.4.4
pandas: 3.0.2
modin:
cudf:
pyarrow: 24.0.0
pyspark:
polars: 1.30.0
dask:
duckdb:
ibis:
sqlframe:
Relevant log output
Additional information
Describe the bug
Narwhals maps pandas sparse columns to
Unknownin schema inference, even though those columns have clear underlying dtypes (for exampleSparse[int64, 0],Sparse[float64, 0.0],Sparse[bool, False]).This appears inconsistent with documentation that says the pandas API is fully supported.
Steps or code to reproduce the bug
Expected results
Narwhals should infer typed columns for pandas sparse arrays (for example
Int64,Float64,Boolean) instead ofUnknown.Actual results
Please run narwhals.show_versions() and enter the output below.
System: python: 3.13.13 | packaged by Anaconda, Inc. | (main, Apr 14 2026, 06:14:06) [Clang 20.1.8 ] executable: /Users/pnl0vq13/miniconda3/envs/lightgbm-dev/bin/python machine: macOS-26.5.1-arm64-arm-64bit-Mach-O Python dependencies: narwhals: 2.22.1 numpy: 2.4.4 pandas: 3.0.2 modin: cudf: pyarrow: 24.0.0 pyspark: polars: 1.30.0 dask: duckdb: ibis: sqlframe:Relevant log output
Additional information
ExtensionArraywith adtypeattribute: https://pandas.pydata.org/docs/reference/api/pandas.api.extensions.ExtensionArray.htmlSparseArrayis anExtensionArray, so this path should have enough dtype information to avoidUnknown.