learnstat 0.1.0__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.
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: learnstat
3
+ Version: 0.1.0
4
+ Summary: An AI-assisted learning companion for statistical analysis with pandas, NumPy, SciPy and Matplotlib.
5
+ License: MIT
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: pandas>=2.0
9
+ Requires-Dist: numpy>=1.24
10
+ Provides-Extra: viz
11
+ Requires-Dist: matplotlib>=3.7; extra == "viz"
12
+ Provides-Extra: stats
13
+ Requires-Dist: scipy>=1.10; extra == "stats"
14
+ Provides-Extra: ai
15
+ Requires-Dist: anthropic>=1.0; extra == "ai"
16
+ Provides-Extra: jupyter
17
+ Requires-Dist: ipython>=8.0; extra == "jupyter"
18
+ Provides-Extra: all
19
+ Requires-Dist: matplotlib>=3.7; extra == "all"
20
+ Requires-Dist: scipy>=1.10; extra == "all"
21
+ Requires-Dist: anthropic>=1.0; extra == "all"
22
+ Requires-Dist: ipython>=8.0; extra == "all"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=7; extra == "dev"
25
+ Requires-Dist: matplotlib>=3.7; extra == "dev"
26
+ Requires-Dist: scipy>=1.10; extra == "dev"
27
+ Requires-Dist: ipython>=8.0; extra == "dev"
28
+
29
+ # learnstat
30
+
31
+ An AI-assisted learning companion for statistical analysis in Python.
32
+
33
+ You write ordinary **pandas / NumPy / SciPy / Matplotlib** code. learnstat:
34
+
35
+ 1. **Understands your dataset.** It profiles the data once and keeps a Markdown memory file of it.
36
+ 2. **Suggests better approaches as you write.** For example, it flags a pie chart of 12 categories and suggests a sorted bar chart, explaining why.
37
+ 3. **Explains itself** through `/describe`, `/alternatives`, `/learn`, `/memory` and `/fix`.
38
+ 4. **Recovers from mechanical errors.** It fixes typos in column names, methods and keywords, plus missing imports and unclosed brackets, and shows you every change.
39
+ 5. **Leaves analytical decisions to you.** Data-quality and statistical-method problems are explained but never "fixed" automatically.
40
+
41
+ It's not a new language. Everything you learn uses the real pandas, SciPy and Matplotlib APIs, so the skills carry over to the rest of the ecosystem.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, anthropic, ipython
47
+ pip install -e . # core only: profiling, rules, recovery (no AI)
48
+ ```
49
+
50
+ The AI features are optional. With the `anthropic` package and credentials set up (`ANTHROPIC_API_KEY` or `ant auth login`), explanations get tailored to your dataset, Claude reviews code with `/review`, and Claude can propose fixes for errors the rules can't handle. Without them, everything else still works offline. The default model is `claude-opus-5-5`; set `LEARNSTAT_MODEL` to choose another.
51
+
52
+ ## Use it
53
+
54
+ ### Jupyter
55
+
56
+ ```python
57
+ %load_ext learnstat
58
+ import learnstat as ls
59
+ df = ls.read_csv("survey.csv") # a normal DataFrame, now profiled into .learnstat/survey.md
60
+ ```
61
+
62
+ ```python
63
+ df["country"].value_counts().plot.pie()
64
+ # [!] Suggestion #1 (line 1): Pie chart with 12 categories
65
+ # Issue: `country` has 12 categories; slices this numerous are hard to compare by angle.
66
+ # Instead: A horizontal bar chart of the counts, sorted by size.
67
+ # Why: Bars share a common baseline ...
68
+ # How: counts = df['country'].value_counts() ...
69
+ ```
70
+
71
+ ```
72
+ /describe <- the concept, why it fits this data, when another method is better
73
+ /accept <- puts the suggested code in a NEW cell; your cell is untouched
74
+ /reject only 3 countries matter here <- recorded in memory, not suggested again
75
+ ```
76
+
77
+ When a cell raises an error, learnstat diagnoses the failing statement. If it's a mechanical mistake, learnstat corrects it, re-runs only that statement and the ones after it, and prints the diff. A cell with a syntax error gets a corrected copy placed in the next cell for you to review.
78
+
79
+ ### Command line
80
+
81
+ ```bash
82
+ cd examples && python make_survey.py
83
+ learnstat profile survey.csv # writes .learnstat/survey.md and prints it
84
+ learnstat check analysis.py # suggestions only, nothing is executed
85
+ learnstat watch analysis.py # re-checks every time you save the file
86
+ learnstat run analysis.py # runs with suggestions and guarded recovery
87
+ learnstat repl --data survey.csv # interactive, with /commands
88
+ ```
89
+
90
+ ### Plain Python
91
+
92
+ ```python
93
+ import learnstat as ls
94
+ df = ls.read_csv("survey.csv")
95
+ ls.check("df['income'].mean()") # suggestions without running
96
+ print(ls.command("/describe"))
97
+
98
+ s = ls.Session(confirm=lambda q: input(q + " [y/N] ") == "y")
99
+ s.ns["df"] = s.read_csv("survey.csv")
100
+ result = s.run("df.groupBy('group')['score'].median()")
101
+ print(result.final_code) # df.groupby(...)... your source is never modified
102
+ ```
103
+
104
+ ## Commands
105
+
106
+ | Command | What it does |
107
+ |---|---|
108
+ | `/describe [id]` | Explains the latest (or given) suggestion, or the latest error: the concept, the purpose of the function, why it fits this data, and when something else is better |
109
+ | `/alternatives [id]` | Other ways to reach the same goal, with trade-offs |
110
+ | `/learn [topic]` | A short lesson with an exercise on your own data |
111
+ | `/fix` | The last error diagnosis; in interactive mode, a retry of the failed statement |
112
+ | `/memory [show\|note\|decide\|refresh]` | View or update the dataset's persistent profile |
113
+ | `/accept [id]`, `/reject [id] [why]` | Accept or reject a suggestion; the decision is saved in memory |
114
+ | `/suggestions`, `/review`, `/ask`, `/status`, `/help` | |
115
+
116
+ ## Dataset memory
117
+
118
+ `ls.read_csv` profiles the data and writes two files to `.learnstat/`:
119
+
120
+ - `survey.md`: columns, types, missing values, likely column meanings (marked as guesses), distributions, relationships, data-quality issues, suggested analyses, assumptions, **your analytical decisions** and notes.
121
+ - `survey.json`: the machine-readable cache. It includes a content fingerprint, so the data is only re-profiled when it actually changes. Decisions and notes carry over when that happens.
122
+
123
+ ## How error recovery stays safe
124
+
125
+ - Code runs **one top-level statement at a time**. When statement *k* fails, only statement *k* is corrected and retried, so earlier side effects are never repeated.
126
+ - Errors are classified as **syntax, name, attribute, argument, column, data-quality, statistical-method, environment** or other runtime errors.
127
+ - Only mechanical mistakes are corrected automatically, and only to a unique, high-similarity match.
128
+ - Before a fix runs, it must compile. It must not introduce file, shell or network operations, must not change which variables are assigned, must not add data-altering calls (`dropna`, `fillna`, `astype` and so on), and must not change the statistical method.
129
+ - AI-proposed fixes always need your confirmation. So does retrying a loop or block, since that could repeat side effects.
130
+ - Retries are bounded (`max_attempts`, 3 by default). If the same error comes back, recovery stops and gives you a concrete next step.
131
+ - Code that deletes or overwrites files, runs shell commands or opens network connections only runs after you confirm.
132
+ - **This is a policy layer, not a sandbox.** Your code runs in your Python process with your permissions, exactly as if you had run it yourself.
133
+
134
+ ## Project layout
135
+
136
+ ```
137
+ learnstat/
138
+ profile.py dataset profiling (no AI)
139
+ memory.py Markdown + JSON dataset memory
140
+ advisor.py AST-based, data-aware suggestion rules
141
+ knowledge.py offline explanations behind /describe, /alternatives, /learn
142
+ recovery.py error diagnosis, fix proposal, validation, bounded retry
143
+ safety.py detection of destructive side effects
144
+ llm.py optional Claude backend
145
+ session.py ties it together; read_csv/track/check/run
146
+ commands.py slash commands
147
+ ipython_ext.py %load_ext learnstat
148
+ cli.py learnstat profile|check|watch|run|repl
149
+ ```
150
+
151
+ Add a rule by writing a function `(call, resolver, code) -> Suggestion | None` in `advisor.py`, appending it to `RULES`, and adding its concept to `knowledge.py`.
152
+
153
+ ## Roadmap
154
+
155
+ - A language-server (LSP) frontend for suggestions while typing in VS Code and JupyterLab. The advisor is already editor-agnostic.
156
+ - More rules: multiple-comparison corrections, chi-square expected counts, normality checks before parametric tests, time-series plotting.
157
+ - Learning-progress tracking, so advice fades as the user masters a concept.
158
+
159
+ ## Tests
160
+
161
+ ```bash
162
+ pip install -e ".[dev]"
163
+ pytest
164
+ ```
@@ -0,0 +1,136 @@
1
+ # learnstat
2
+
3
+ An AI-assisted learning companion for statistical analysis in Python.
4
+
5
+ You write ordinary **pandas / NumPy / SciPy / Matplotlib** code. learnstat:
6
+
7
+ 1. **Understands your dataset.** It profiles the data once and keeps a Markdown memory file of it.
8
+ 2. **Suggests better approaches as you write.** For example, it flags a pie chart of 12 categories and suggests a sorted bar chart, explaining why.
9
+ 3. **Explains itself** through `/describe`, `/alternatives`, `/learn`, `/memory` and `/fix`.
10
+ 4. **Recovers from mechanical errors.** It fixes typos in column names, methods and keywords, plus missing imports and unclosed brackets, and shows you every change.
11
+ 5. **Leaves analytical decisions to you.** Data-quality and statistical-method problems are explained but never "fixed" automatically.
12
+
13
+ It's not a new language. Everything you learn uses the real pandas, SciPy and Matplotlib APIs, so the skills carry over to the rest of the ecosystem.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install -e ".[all]" # pandas, numpy, matplotlib, scipy, anthropic, ipython
19
+ pip install -e . # core only: profiling, rules, recovery (no AI)
20
+ ```
21
+
22
+ The AI features are optional. With the `anthropic` package and credentials set up (`ANTHROPIC_API_KEY` or `ant auth login`), explanations get tailored to your dataset, Claude reviews code with `/review`, and Claude can propose fixes for errors the rules can't handle. Without them, everything else still works offline. The default model is `claude-opus-5-5`; set `LEARNSTAT_MODEL` to choose another.
23
+
24
+ ## Use it
25
+
26
+ ### Jupyter
27
+
28
+ ```python
29
+ %load_ext learnstat
30
+ import learnstat as ls
31
+ df = ls.read_csv("survey.csv") # a normal DataFrame, now profiled into .learnstat/survey.md
32
+ ```
33
+
34
+ ```python
35
+ df["country"].value_counts().plot.pie()
36
+ # [!] Suggestion #1 (line 1): Pie chart with 12 categories
37
+ # Issue: `country` has 12 categories; slices this numerous are hard to compare by angle.
38
+ # Instead: A horizontal bar chart of the counts, sorted by size.
39
+ # Why: Bars share a common baseline ...
40
+ # How: counts = df['country'].value_counts() ...
41
+ ```
42
+
43
+ ```
44
+ /describe <- the concept, why it fits this data, when another method is better
45
+ /accept <- puts the suggested code in a NEW cell; your cell is untouched
46
+ /reject only 3 countries matter here <- recorded in memory, not suggested again
47
+ ```
48
+
49
+ When a cell raises an error, learnstat diagnoses the failing statement. If it's a mechanical mistake, learnstat corrects it, re-runs only that statement and the ones after it, and prints the diff. A cell with a syntax error gets a corrected copy placed in the next cell for you to review.
50
+
51
+ ### Command line
52
+
53
+ ```bash
54
+ cd examples && python make_survey.py
55
+ learnstat profile survey.csv # writes .learnstat/survey.md and prints it
56
+ learnstat check analysis.py # suggestions only, nothing is executed
57
+ learnstat watch analysis.py # re-checks every time you save the file
58
+ learnstat run analysis.py # runs with suggestions and guarded recovery
59
+ learnstat repl --data survey.csv # interactive, with /commands
60
+ ```
61
+
62
+ ### Plain Python
63
+
64
+ ```python
65
+ import learnstat as ls
66
+ df = ls.read_csv("survey.csv")
67
+ ls.check("df['income'].mean()") # suggestions without running
68
+ print(ls.command("/describe"))
69
+
70
+ s = ls.Session(confirm=lambda q: input(q + " [y/N] ") == "y")
71
+ s.ns["df"] = s.read_csv("survey.csv")
72
+ result = s.run("df.groupBy('group')['score'].median()")
73
+ print(result.final_code) # df.groupby(...)... your source is never modified
74
+ ```
75
+
76
+ ## Commands
77
+
78
+ | Command | What it does |
79
+ |---|---|
80
+ | `/describe [id]` | Explains the latest (or given) suggestion, or the latest error: the concept, the purpose of the function, why it fits this data, and when something else is better |
81
+ | `/alternatives [id]` | Other ways to reach the same goal, with trade-offs |
82
+ | `/learn [topic]` | A short lesson with an exercise on your own data |
83
+ | `/fix` | The last error diagnosis; in interactive mode, a retry of the failed statement |
84
+ | `/memory [show\|note\|decide\|refresh]` | View or update the dataset's persistent profile |
85
+ | `/accept [id]`, `/reject [id] [why]` | Accept or reject a suggestion; the decision is saved in memory |
86
+ | `/suggestions`, `/review`, `/ask`, `/status`, `/help` | |
87
+
88
+ ## Dataset memory
89
+
90
+ `ls.read_csv` profiles the data and writes two files to `.learnstat/`:
91
+
92
+ - `survey.md`: columns, types, missing values, likely column meanings (marked as guesses), distributions, relationships, data-quality issues, suggested analyses, assumptions, **your analytical decisions** and notes.
93
+ - `survey.json`: the machine-readable cache. It includes a content fingerprint, so the data is only re-profiled when it actually changes. Decisions and notes carry over when that happens.
94
+
95
+ ## How error recovery stays safe
96
+
97
+ - Code runs **one top-level statement at a time**. When statement *k* fails, only statement *k* is corrected and retried, so earlier side effects are never repeated.
98
+ - Errors are classified as **syntax, name, attribute, argument, column, data-quality, statistical-method, environment** or other runtime errors.
99
+ - Only mechanical mistakes are corrected automatically, and only to a unique, high-similarity match.
100
+ - Before a fix runs, it must compile. It must not introduce file, shell or network operations, must not change which variables are assigned, must not add data-altering calls (`dropna`, `fillna`, `astype` and so on), and must not change the statistical method.
101
+ - AI-proposed fixes always need your confirmation. So does retrying a loop or block, since that could repeat side effects.
102
+ - Retries are bounded (`max_attempts`, 3 by default). If the same error comes back, recovery stops and gives you a concrete next step.
103
+ - Code that deletes or overwrites files, runs shell commands or opens network connections only runs after you confirm.
104
+ - **This is a policy layer, not a sandbox.** Your code runs in your Python process with your permissions, exactly as if you had run it yourself.
105
+
106
+ ## Project layout
107
+
108
+ ```
109
+ learnstat/
110
+ profile.py dataset profiling (no AI)
111
+ memory.py Markdown + JSON dataset memory
112
+ advisor.py AST-based, data-aware suggestion rules
113
+ knowledge.py offline explanations behind /describe, /alternatives, /learn
114
+ recovery.py error diagnosis, fix proposal, validation, bounded retry
115
+ safety.py detection of destructive side effects
116
+ llm.py optional Claude backend
117
+ session.py ties it together; read_csv/track/check/run
118
+ commands.py slash commands
119
+ ipython_ext.py %load_ext learnstat
120
+ cli.py learnstat profile|check|watch|run|repl
121
+ ```
122
+
123
+ Add a rule by writing a function `(call, resolver, code) -> Suggestion | None` in `advisor.py`, appending it to `RULES`, and adding its concept to `knowledge.py`.
124
+
125
+ ## Roadmap
126
+
127
+ - A language-server (LSP) frontend for suggestions while typing in VS Code and JupyterLab. The advisor is already editor-agnostic.
128
+ - More rules: multiple-comparison corrections, chi-square expected counts, normality checks before parametric tests, time-series plotting.
129
+ - Learning-progress tracking, so advice fades as the user masters a concept.
130
+
131
+ ## Tests
132
+
133
+ ```bash
134
+ pip install -e ".[dev]"
135
+ pytest
136
+ ```
@@ -0,0 +1,80 @@
1
+ """learnstat - an AI-assisted learning companion for statistics in Python.
2
+
3
+ You write ordinary pandas / NumPy / SciPy / Matplotlib code; learnstat profiles
4
+ your data, suggests better approaches, explains its reasoning and helps you
5
+ recover from mistakes.
6
+
7
+ import learnstat as ls
8
+ df = ls.read_csv("survey.csv") # a normal pandas DataFrame, now profiled
9
+ ls.check("df['income'].mean()") # suggestions, without running anything
10
+ print(ls.command("/describe")) # why?
11
+
12
+ In Jupyter: ``%load_ext learnstat``.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from .advisor import CodeAdvisor
18
+ from .memory import MemoryStore
19
+ from .profile import DatasetProfile, profile_dataframe
20
+ from .recovery import Executor, RunResult
21
+ from .session import Session, get_session, set_session
22
+ from .suggestions import Suggestion
23
+
24
+ __version__ = "0.1.0"
25
+
26
+
27
+ def read_csv(path, name: str | None = None, **kwargs):
28
+ """``pandas.read_csv`` plus dataset profiling and persistent memory."""
29
+ return get_session().read_csv(path, name=name, **kwargs)
30
+
31
+
32
+ def read_excel(path, name: str | None = None, **kwargs):
33
+ return get_session().read_excel(path, name=name, **kwargs)
34
+
35
+
36
+ def read_parquet(path, name: str | None = None, **kwargs):
37
+ return get_session().read_parquet(path, name=name, **kwargs)
38
+
39
+
40
+ def read_json(path, name: str | None = None, **kwargs):
41
+ return get_session().read_json(path, name=name, **kwargs)
42
+
43
+
44
+ def track(df, name: str | None = None, **kwargs):
45
+ """Profile a DataFrame you already have."""
46
+ return get_session().track(df, name=name, **kwargs)
47
+
48
+
49
+ def check(code: str, show: bool = True):
50
+ """Suggestions for ``code`` (it is not executed)."""
51
+ return get_session().check(code, show=show)
52
+
53
+
54
+ def run(code: str):
55
+ """Run ``code`` in the default session with suggestions and guarded recovery."""
56
+ return get_session().run(code)
57
+
58
+
59
+ def command(text: str) -> str:
60
+ """Run a slash command such as ``/describe`` and return its text."""
61
+ return get_session().command(text)
62
+
63
+
64
+ def load_ipython_extension(ip):
65
+ from .ipython_ext import load_ipython_extension as _load
66
+
67
+ _load(ip)
68
+
69
+
70
+ def unload_ipython_extension(ip):
71
+ from .ipython_ext import unload_ipython_extension as _unload
72
+
73
+ _unload(ip)
74
+
75
+
76
+ __all__ = [
77
+ "Session", "get_session", "set_session", "read_csv", "read_excel", "read_parquet", "read_json",
78
+ "track", "check", "run", "command", "profile_dataframe", "DatasetProfile", "MemoryStore",
79
+ "CodeAdvisor", "Executor", "RunResult", "Suggestion",
80
+ ]