Skip to content

Commit d208b22

Browse files
committed
v0.1.0a17: tbl_one Rao-Scott footnote grade + NaN weight guard
Two fixes from external adversarial audit: F-02: Rao-Scott rendered table footnote now names the first-order Kish-DEFF approximation and its known disagreement range with R survey::svychisq (10-15% or more under high ICC). Previously the footnote only said "Tests: Rao-Scott chi-square" with no grade qualifier — invisible in published HTML/PDF tables even though the UserWarning existed. A separate footnote line is appended whenever the Rao-Scott test appears in test_names. F-03: tbl_one() now raises ValueError when the weights column contains NaN values, matching tbl_regression() behavior. Previously NaN weights were silently coerced to 0, which caused the affected group to display N=0 and all statistics as em-dashes with no user signal. The error message names the column and suggests a fix.
1 parent 738b647 commit d208b22

3 files changed

Lines changed: 16 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "pysofra"
7-
version = "0.1.0a16"
7+
version = "0.1.0a17"
88
description = "Statistical reporting and table preparation framework for Python — the missing reporting layer."
99
readme = "README.md"
1010
license = { text = "GPL-3.0-or-later" }

src/pysofra/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
from .summary.tests import available_tests
5151
from .themes.registry import available_themes, register_theme
5252

53-
__version__ = "0.1.0a16"
53+
__version__ = "0.1.0a17"
5454

5555
__all__ = [
5656
"CellPart",

src/pysofra/summary/tbl_one.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ def tbl_one(
159159
"Negative weights are not supported; drop or correct them "
160160
"before calling tbl_one()."
161161
)
162+
n_nan = int(w_col.isna().sum())
163+
if n_nan > 0:
164+
raise ValueError(
165+
f"weights column {weights!r} contains {n_nan} NaN value(s). "
166+
"Drop or impute missing weights before calling tbl_one(). "
167+
"(Use data.dropna(subset=[weights_col]) or fill with a "
168+
"suitable value first.)"
169+
)
162170
total = float(w_col.fillna(0.0).sum())
163171
if total <= 0:
164172
raise ValueError(
@@ -454,6 +462,12 @@ def _fmt_n(val: float | int) -> str:
454462
footnotes.append("n (%) for categorical variables.")
455463
if show_p and test_names:
456464
footnotes.append("Tests: " + "; ".join(sorted(test_names)) + ".")
465+
if "Rao–Scott chi-square" in test_names:
466+
footnotes.append(
467+
"Rao–Scott chi-square: first-order Kish-DEFF approximation; "
468+
"may disagree with R survey::svychisq (second-order) by 10–15 % "
469+
"or more under complex designs with strong intra-cluster correlation."
470+
)
457471
if show_q:
458472
footnotes.append(f"q-value = {_q_method_label(q_method)} adjusted p-value.")
459473
if show_smd:

0 commit comments

Comments
 (0)