Skip to content

Commit fdcdcf7

Browse files
Issue 283 nano plot scaling (#404)
* Filter rows correctly for nanoplot scaling * Tests row selection used for scaling nanoplots * Add comments to nanoplot SVG comparison tests --------- Co-authored-by: Richard Iannone <riannone@me.com>
1 parent ee5f110 commit fdcdcf7

2 files changed

Lines changed: 82 additions & 3 deletions

File tree

great_tables/_formats.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5287,7 +5287,10 @@ def fmt_nanoplot(
52875287
if plot_type in ("line", "bar") and scalar_vals:
52885288
# Check each cell in the column and get each of them that contains a scalar value
52895289
# Why are we grabbing the first element of a tuple? (Note this also happens again below.)
5290-
all_single_y_vals = to_list(data_tbl[columns])
5290+
if rows is not None:
5291+
all_single_y_vals = to_list(data_tbl[columns][rows])
5292+
else:
5293+
all_single_y_vals = to_list(data_tbl[columns])
52915294

52925295
autoscale = False
52935296

@@ -5308,7 +5311,10 @@ def fmt_nanoplot(
53085311
# TODO: if a column of delimiter separated strings is passed. E.g. "1 2 3 4". Does this mean
53095312
# that autoscale does not work? In this case, is col_i_y_vals_raw a string that gets processed?
53105313
# downstream?
5311-
all_y_vals_raw = to_list(data_tbl[columns])
5314+
if rows is not None:
5315+
all_y_vals_raw = to_list(data_tbl[columns][rows])
5316+
else:
5317+
all_y_vals_raw = to_list(data_tbl[columns])
53125318

53135319
all_y_vals = []
53145320

tests/test_formats.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,8 @@ def _nanoplot_has_tag_attrs(nanoplot_str: str, tag: str, attrs: list[tuple[str,
22102210

22112211
df_fmt_nanoplot_single = pl.DataFrame({"vals": [-5.3, 6.3]})
22122212

2213+
df_fmt_nanoplot_single_different_scales = pl.DataFrame({"vals": [-5.3, 100.0]})
2214+
22132215
df_fmt_nanoplot_multi = pl.DataFrame(
22142216
{
22152217
"vals": [
@@ -2219,6 +2221,15 @@ def _nanoplot_has_tag_attrs(nanoplot_str: str, tag: str, attrs: list[tuple[str,
22192221
}
22202222
)
22212223

2224+
df_fmt_nanoplot_multi_different_scales = pl.DataFrame(
2225+
{
2226+
"vals": [
2227+
{"x": [-12.0, -5.0, 6.0, 3.0, 0.0, 8.0, -7.0]},
2228+
{"x": [2, 0, 150, 7, 80, 10, 10, 240, 17, 13, 6]},
2229+
],
2230+
}
2231+
)
2232+
22222233
FMT_NANOPLOT_CASES: list[dict[str, Any]] = [
22232234
# 1. default case
22242235
dict(),
@@ -2584,7 +2595,69 @@ def test_fmt_nanoplot_multi_vals_bar_ref_line_ref_area():
25842595
)
25852596

25862597

2587-
# Test category 8: Line-based nanoplot, multiple values per row, reference line and reference area
2598+
# Test category 8: Scale unaffected by unselected rows for single line plot
2599+
def test_fmt_nanoplot_single_vals_same_values_in_selected_rows():
2600+
# All test cases should have the same scale for each plot when their values are the same in
2601+
# in selected rows, ignoring values in unselected rows
2602+
2603+
for _, params in enumerate(FMT_NANOPLOT_CASES):
2604+
gt = GT(df_fmt_nanoplot_single).fmt_nanoplot(
2605+
columns="vals",
2606+
plot_type="line",
2607+
rows=[0],
2608+
**params,
2609+
)
2610+
2611+
gt_different_scales = GT(df_fmt_nanoplot_single_different_scales).fmt_nanoplot(
2612+
columns="vals",
2613+
plot_type="line",
2614+
rows=[0],
2615+
**params,
2616+
)
2617+
2618+
# Compare the fully-rendered SVG output for row 0 from both DataFrames;
2619+
# if scaling incorrectly included the non-selected row, the different
2620+
# values in row 1 would alter the SVG coordinates and break equality
2621+
res = _get_column_of_values(gt, column_name="vals", context="html")[0]
2622+
res_different_scales = _get_column_of_values(
2623+
gt_different_scales, column_name="vals", context="html"
2624+
)[0]
2625+
assert res == res_different_scales
2626+
2627+
2628+
# Test category 9: Scale unaffected by unselected rows for line plot with multiple values
2629+
def test_fmt_nanoplot_multiple_vals_same_values_in_selected_rows_with_autoscale():
2630+
# All test cases should have the same scale for each plot when their values are the same in
2631+
# in selected rows and autoscale is used, ignoring values in unselected rows
2632+
2633+
for _, params in enumerate(FMT_NANOPLOT_CASES):
2634+
gt = GT(df_fmt_nanoplot_multi).fmt_nanoplot(
2635+
columns="vals",
2636+
plot_type="line",
2637+
rows=[0],
2638+
autoscale=True,
2639+
**params,
2640+
)
2641+
2642+
gt_different_scales = GT(df_fmt_nanoplot_multi_different_scales).fmt_nanoplot(
2643+
columns="vals",
2644+
plot_type="line",
2645+
rows=[0],
2646+
autoscale=True,
2647+
**params,
2648+
)
2649+
2650+
# Compare the fully-rendered SVG output for row 0 from both DataFrames;
2651+
# if autoscale incorrectly included the non-selected row, the different
2652+
# values in row 1 would change expand_y bounds and alter SVG coordinates
2653+
res = _get_column_of_values(gt, column_name="vals", context="html")[0]
2654+
res_different_scales = _get_column_of_values(
2655+
gt_different_scales, column_name="vals", context="html"
2656+
)[0]
2657+
assert res == res_different_scales
2658+
2659+
2660+
# Test category 10: Line-based nanoplot, multiple values per row, reference line and reference area
25882661
def test_fmt_nanoplot_x_y_vals():
25892662
df_fmt_nanoplot_multi_xy = pl.DataFrame(
25902663
{

0 commit comments

Comments
 (0)