Skip to content

Commit ff3709c

Browse files
KristijanArmenimachowrich-iannone
authored
fix: Convert Polars container dtype entries to list in _get_cell (#778) (#794)
* fix: convert container type entries to list in polars tables * refactor: use tuple for second arg in isinstance * test: test _get_cell for container dtypes * Guard None before to_list() for list cells * Handle None in container dtype tests * Include pl.Array in list column detection * refactor: simplify list-column check --------- Co-authored-by: Michael Chow <mc_al_github@fastmail.com> Co-authored-by: Richard Iannone <riannone@me.com>
1 parent 3596881 commit ff3709c

2 files changed

Lines changed: 47 additions & 5 deletions

File tree

great_tables/_tbl_data.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,15 @@ def _get_cell(data: DataFrameLike, row: int, column: str) -> Any:
224224

225225
@_get_cell.register(PlDataFrame)
226226
def _(data: Any, row: int, column: str) -> Any:
227-
return data[column][row]
227+
import polars as pl
228+
229+
res = data[column][row]
230+
231+
# container dtypes (pl.List, pl.Array) return a pl.Series
232+
if isinstance(res, pl.Series):
233+
return res.to_list()
234+
235+
return res
228236

229237

230238
@_get_cell.register(PdDataFrame)
@@ -570,7 +578,9 @@ def _(df: PlDataFrame):
570578
import polars.selectors as cs
571579

572580
list_cols = [
573-
name for name, dtype in df.schema.items() if issubclass(dtype.base_type(), pl.List)
581+
name
582+
for name, dtype in df.schema.items()
583+
if issubclass(dtype.base_type(), (pl.List, pl.Array))
574584
]
575585

576586
return df.with_columns(

tests/test_tbl_data.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import math
2+
23
import pandas as pd
34
import polars as pl
4-
import pyarrow as pa
55
import polars.testing
6+
import pyarrow as pa
67
import pytest
8+
79
from great_tables import GT
8-
from great_tables._utils_render_html import create_body_component_h
910
from great_tables._tbl_data import (
1011
DataFrameLike,
1112
SeriesLike,
@@ -14,6 +15,7 @@
1415
_set_cell,
1516
_validate_selector_list,
1617
cast_frame_to_string,
18+
copy_frame,
1719
create_empty_frame,
1820
eval_aggregate,
1921
eval_select,
@@ -24,8 +26,8 @@
2426
to_frame,
2527
to_list,
2628
validate_frame,
27-
copy_frame,
2829
)
30+
from great_tables._utils_render_html import create_body_component_h
2931

3032
params_frames = [
3133
pytest.param(pd.DataFrame, id="pandas"),
@@ -38,13 +40,37 @@
3840
pytest.param(pa.array, id="arrow"),
3941
pytest.param(lambda a: pa.chunked_array([a]), id="arrow-chunked"),
4042
]
43+
params_pl_container_dtypes = [
44+
pytest.param(pl.List, id="list"),
45+
pytest.param(pl.Array, id="array"),
46+
]
4147

4248

4349
@pytest.fixture(params=params_frames, scope="function")
4450
def df(request) -> pd.DataFrame:
4551
return request.param({"col1": [1, 2, 3], "col2": ["a", "b", "c"], "col3": [4.0, 5.0, 6.0]})
4652

4753

54+
@pytest.fixture(params=params_pl_container_dtypes, scope="function")
55+
def df_container_dtypes(request):
56+
dtype_constructor = request.param
57+
58+
if dtype_constructor == pl.List:
59+
return pl.DataFrame(
60+
{"col1": [1, 2, 3], "col2": [[1, 2, 3], [4, 5], None], "col3": ["a", "b", "c"]}
61+
)
62+
# return a pl df with pl.Array columns
63+
else:
64+
col2_as_array = pl.col("col2").cast(pl.Array(pl.Int32, shape=(3,)))
65+
return pl.DataFrame(
66+
{
67+
"col1": [1, 2, 3],
68+
"col2": [[1, 2, 3], [4, 5, 6], None],
69+
"col3": ["a", "b", "c"],
70+
}
71+
).with_columns(col2_as_array)
72+
73+
4874
@pytest.fixture(params=params_series, scope="function")
4975
def ser(request) -> SeriesLike:
5076
return request.param([1.0, 2.0, None])
@@ -75,6 +101,12 @@ def test_get_cell(df: DataFrameLike):
75101
assert _get_cell(df, 1, "col2") == "b"
76102

77103

104+
def test_get_cell_container_dtypes(df_container_dtypes: pl.DataFrame):
105+
"Checks that container dtype entries in polars dfs are returned as lists"
106+
assert isinstance(_get_cell(df_container_dtypes, 0, "col2"), list)
107+
assert _get_cell(df_container_dtypes, 2, "col2") is None
108+
109+
78110
def test_set_cell(df: DataFrameLike):
79111
expected_data = {"col1": [1, 2, 3], "col2": ["a", "x", "c"], "col3": [4.0, 5.0, 6.0]}
80112
if isinstance(df, pa.Table):

0 commit comments

Comments
 (0)