dataframe-toolkit 0.7.1__tar.gz → 0.7.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/PKG-INFO +16 -1
  2. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/README.md +14 -0
  3. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/pyproject.toml +2 -1
  4. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/pyproject.toml.orig +2 -1
  5. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/concat_cmd.py +13 -4
  6. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/fit_cmd.py +19 -5
  7. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/stat_cmd.py +3 -0
  8. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/__init__.py +0 -0
  9. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/cli.py +0 -0
  10. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/__init__.py +0 -0
  11. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/annotate_cmd.py +0 -0
  12. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/base.py +0 -0
  13. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/binx_cmd.py +0 -0
  14. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/chi_cmd.py +0 -0
  15. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/clean_cmd.py +0 -0
  16. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/corr_cmd.py +0 -0
  17. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/dataset_cmd.py +0 -0
  18. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/describe_cmd.py +0 -0
  19. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/eval_cmd.py +0 -0
  20. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/func_cmd.py +0 -0
  21. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/help.py +0 -0
  22. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/hist_cmd.py +0 -0
  23. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/info_cmd.py +0 -0
  24. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/interp_cmd.py +0 -0
  25. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/line_cmd.py +0 -0
  26. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/melt_cmd.py +0 -0
  27. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/merge_cmd.py +0 -0
  28. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/pivot_cmd.py +0 -0
  29. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/print_cmd.py +0 -0
  30. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/query_cmd.py +0 -0
  31. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/randvar_cmd.py +0 -0
  32. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/sample_cmd.py +0 -0
  33. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/scale_cmd.py +0 -0
  34. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/scat_cmd.py +0 -0
  35. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/segid_cmd.py +0 -0
  36. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/split_cmd.py +0 -0
  37. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/test_cmd.py +0 -0
  38. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/transpose_cmd.py +0 -0
  39. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/commands/wstat_cmd.py +0 -0
  40. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/__init__.py +0 -0
  41. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/copula.py +0 -0
  42. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/io.py +0 -0
  43. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/plot.py +0 -0
  44. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/seed.py +0 -0
  45. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/seq.py +0 -0
  46. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/common/stats.py +0 -0
  47. {dataframe_toolkit-0.7.1 → dataframe_toolkit-0.7.2}/src/dftk/io.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dataframe-toolkit
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: A command-line toolkit for DataFrame analysis and manipulation
5
5
  Keywords: dataframe,statistics,data analysis,CLI,TSV,pandas
6
6
  Author: Gunnar Pálsson
@@ -17,6 +17,7 @@ Requires-Dist: numpy>=1.24
17
17
  Requires-Dist: pyarrow>=12.0
18
18
  Requires-Dist: scipy>=1.10
19
19
  Requires-Dist: statsmodels>=0.14
20
+ Requires-Dist: patsy>=0.5.6
20
21
  Requires-Dist: duckdb>=0.8
21
22
  Requires-Dist: matplotlib>=3.7
22
23
  Requires-Dist: seaborn>=0.12
@@ -73,6 +74,20 @@ cd dataframe-toolkit
73
74
  uv tool install .
74
75
  ```
75
76
 
77
+ ### Skill for coding agents
78
+
79
+ `skills/dftk/` is an agent skill: a short guide that coding agents such as
80
+ Codex and Claude Code load when a task involves dftk. It covers the piping
81
+ conventions, which command to use for what, and patterns for Snakemake and
82
+ Make. Copy it into your agent's skills directory, for example:
83
+
84
+ ```bash
85
+ cp -r skills/dftk ~/.codex/skills/ # Codex
86
+ cp -r skills/dftk ~/.claude/skills/ # Claude Code
87
+ ```
88
+
89
+ Copy it again after upgrading dftk so it matches the installed version.
90
+
76
91
  ## Quick example
77
92
 
78
93
  ```bash
@@ -45,6 +45,20 @@ cd dataframe-toolkit
45
45
  uv tool install .
46
46
  ```
47
47
 
48
+ ### Skill for coding agents
49
+
50
+ `skills/dftk/` is an agent skill: a short guide that coding agents such as
51
+ Codex and Claude Code load when a task involves dftk. It covers the piping
52
+ conventions, which command to use for what, and patterns for Snakemake and
53
+ Make. Copy it into your agent's skills directory, for example:
54
+
55
+ ```bash
56
+ cp -r skills/dftk ~/.codex/skills/ # Codex
57
+ cp -r skills/dftk ~/.claude/skills/ # Claude Code
58
+ ```
59
+
60
+ Copy it again after upgrading dftk so it matches the installed version.
61
+
48
62
  ## Quick example
49
63
 
50
64
  ```bash
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dataframe-toolkit"
3
- version = "0.7.1"
3
+ version = "0.7.2"
4
4
  description = "A command-line toolkit for DataFrame analysis and manipulation"
5
5
  readme = "README.md"
6
6
  keywords = [
@@ -26,6 +26,7 @@ dependencies = [
26
26
  "pyarrow>=12.0",
27
27
  "scipy>=1.10",
28
28
  "statsmodels>=0.14",
29
+ "patsy>=0.5.6",
29
30
  "duckdb>=0.8",
30
31
  "matplotlib>=3.7",
31
32
  "seaborn>=0.12",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dataframe-toolkit"
3
- version = "0.7.1"
3
+ version = "0.7.2"
4
4
  description = "A command-line toolkit for DataFrame analysis and manipulation"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -23,6 +23,7 @@ dependencies = [
23
23
  "pyarrow>=12.0",
24
24
  "scipy>=1.10",
25
25
  "statsmodels>=0.14",
26
+ "patsy>=0.5.6",
26
27
  "duckdb>=0.8",
27
28
  "matplotlib>=3.7",
28
29
  "seaborn>=0.12",
@@ -40,6 +40,8 @@ COLUMN ALIGNMENT
40
40
  ----------------
41
41
  Columns present in all files are aligned by name.
42
42
  Columns missing from some files are filled with NaN (or --fill value).
43
+ --fill applies only to those missing columns: a cell that is empty within
44
+ a file stays empty.
43
45
  Use --select to enforce a fixed output column set.
44
46
 
45
47
  EXAMPLES
@@ -79,7 +81,8 @@ Mismatched columns are outer-joined and filled (NaN by default, or --fill):
79
81
  metavar="VALUE",
80
82
  help=(
81
83
  "Fill value for columns absent in some files "
82
- "(default: NaN). Use 0 or '' for numeric/string defaults."
84
+ "(default: NaN). Use 0 or '' for numeric/string defaults. "
85
+ "Cells that are empty within a file stay empty."
83
86
  ),
84
87
  )
85
88
 
@@ -152,8 +155,6 @@ Mismatched columns are outer-joined and filled (NaN by default, or --fill):
152
155
  if not dfs:
153
156
  raise ValueError("concat: no data read from any input file")
154
157
 
155
- result = pd.concat(dfs, ignore_index=True)
156
-
157
158
  if args.fill is not None:
158
159
  fill: int | float | str
159
160
  try:
@@ -163,6 +164,14 @@ Mismatched columns are outer-joined and filled (NaN by default, or --fill):
163
164
  fill = float(args.fill)
164
165
  except ValueError:
165
166
  fill = args.fill
166
- result = result.fillna(fill)
167
+ # Add each file's missing columns before stacking, so --fill
168
+ # touches only those, not cells that were already empty in a file.
169
+ columns = list(dict.fromkeys(c for df in dfs for c in df.columns))
170
+ dfs = [
171
+ df.assign(**{c: fill for c in columns if c not in df.columns})[columns]
172
+ for df in dfs
173
+ ]
174
+
175
+ result = pd.concat(dfs, ignore_index=True)
167
176
 
168
177
  io.printdf(result, args)
@@ -34,10 +34,12 @@ tidy coefficient tables into one output dataframe.
34
34
  import argparse
35
35
  import logging
36
36
 
37
+ import numpy as np # noqa: F401 — for formulas such as "np.log(y) ~ x", see below
37
38
  import pandas as pd
38
39
  import statsmodels.api as sm
39
40
  import statsmodels.formula.api as smf
40
41
  import statsmodels.stats.anova as sa
42
+ from patsy import PatsyError
41
43
 
42
44
  from dftk.commands.base import BaseCommand
43
45
  from dftk.common.io import check_cols, io
@@ -50,6 +52,11 @@ logger = logging.getLogger(__name__)
50
52
  # ---------------------------------------------------------------------------
51
53
 
52
54
 
55
+ # Formulas are evaluated in the namespace of the function that builds the
56
+ # model (statsmodels' default eval_env), i.e. this module's globals — which
57
+ # is why numpy is imported above as np.
58
+
59
+
53
60
  def standard_model(df: pd.DataFrame, args: argparse.Namespace):
54
61
  """Return an OLS or RLM (robust) model, not yet fitted."""
55
62
  if getattr(args, "robust", False):
@@ -67,11 +74,18 @@ def weighted_model(df: pd.DataFrame, args: argparse.Namespace):
67
74
 
68
75
 
69
76
  def regress_it(df: pd.DataFrame, args: argparse.Namespace):
70
- """Fit the appropriate model and return the fitted result object."""
71
- if getattr(args, "weights", None) is not None:
72
- mod = weighted_model(df, args)
73
- else:
74
- mod = standard_model(df, args)
77
+ """Fit the appropriate model and return the fitted result object.
78
+
79
+ A formula that cannot be evaluated (unknown column or function) raises
80
+ ValueError, which the CLI reports as an input error.
81
+ """
82
+ try:
83
+ if getattr(args, "weights", None) is not None:
84
+ mod = weighted_model(df, args)
85
+ else:
86
+ mod = standard_model(df, args)
87
+ except PatsyError as exc:
88
+ raise ValueError(f"cannot evaluate formula {args.formula!r}: {exc}") from None
75
89
  return mod.fit()
76
90
 
77
91
 
@@ -132,6 +132,9 @@ def _compute_stats(df: pd.DataFrame, args: argparse.Namespace) -> pd.DataFrame:
132
132
  stats = (
133
133
  df[cols].agg(agg_funcs).T.reset_index().rename(columns={"index": "name"})
134
134
  )
135
+ # Before the transpose each column held count and the float stats
136
+ # together, so count came out as float; a count is never missing.
137
+ stats["count"] = stats["count"].astype("int64")
135
138
  return stats[["name"] + _STAT_NAMES]
136
139
 
137
140
  else: