Skill Tracer
Skills › Scientific Agent Skills › exploratory-data-analysis › distribution_sensitivity.py

distribution_sensitivity.py

117 lines · skills/exploratory-data-analysis/scripts/distribution_sensitivity.py at 5f2bc03

1#!/usr/bin/env python3
2"""Bounded distribution, transformation, and outlier sensitivity CLI."""
3
4from __future__ import annotations
5
6import argparse
7
8from _capabilities import capability_for_path
9from _common import (
10 DEFAULT_MAX_FILE_BYTES,
11 DEFAULT_MAX_ROWS,
12 bounded_file_limit,
13 checked_input_file,
14 emit_json,
15 run_cli,
17from _tabular import audit_distributions
20def build_parser() -> argparse.ArgumentParser:
21 parser = argparse.ArgumentParser(
22 description=(
23 "Compare classical and robust summaries on bounded CSV/TSV data. "
24 "The command never deletes, winsorizes, transforms, or imputes source data."
25 )
26 )
27 parser.add_argument("input", help="Local .csv or .tsv path inside --root")
28 parser.add_argument(
29 "--root",
30 default=".",
31 help="Existing local directory that bounds all input/output paths",
32 )
33 parser.add_argument(
34 "--max-bytes",
35 type=int,
36 default=DEFAULT_MAX_FILE_BYTES,
37 help=f"Maximum input bytes (hard ceiling: {512 * 1024 * 1024})",
38 )
39 parser.add_argument(
40 "--max-rows",
41 type=int,
42 default=DEFAULT_MAX_ROWS,
43 help="Maximum rows to scan (hard ceiling: 1000000)",
44 )
45 parser.add_argument(
46 "--column",
47 action="append",
48 help=(
49 "Exact numeric column identifier; repeat as needed. Without this flag, "
50 "the first 64 columns are screened."
51 ),
52 )
53 parser.add_argument(
54 "--missing-token",
55 action="append",
56 help="Explicit additional missing code; repeat as needed",
57 )
58 parser.add_argument(
59 "--reveal-identifiers",
60 action="store_true",
61 help="Emit sanitized column identifiers; values remain redacted",
62 )
63 parser.add_argument("--output", help="Optional local .json output path")
64 parser.add_argument(
65 "--force",
66 action="store_true",
67 help="Allow replacement of an existing regular output file",
68 )
69 return parser
72def _main() -> None:
73 args = build_parser().parse_args()
74 max_bytes = bounded_file_limit(args.max_bytes)
75 path = checked_input_file(
76 args.input,
77 root=args.root,
78 suffixes={".csv", ".tsv"},
79 max_bytes=max_bytes,
80 )
81 report = {
82 "schema_version": "1.1",
83 "capability": capability_for_path(path),
84 "analysis": audit_distributions(
85 path,
86 columns=args.column,
87 max_rows=args.max_rows,
88 missing_tokens=args.missing_token,
89 reveal_identifiers=args.reveal_identifiers,
90 ),
91 "security": {
92 "local_only": True,
93 "file_text_is_untrusted_data": True,
94 "embedded_instructions_followed": False,
95 "raw_values_and_paths_emitted": False,
96 },
97 "decisions": {
98 "automatic_outlier_deletion": False,
99 "automatic_transformation": False,
100 "automatic_imputation": False,
101 "hypothesis_tests_run": 0,
102 },
103 }
104 emit_json(
105 report,
106 output=args.output,
107 root=args.root,
108 force=args.force,
109 )
112def main() -> int:
113 return run_cli(_main)
116if __name__ == "__main__":
117 raise SystemExit(main())