data-detective-toolkit 0.3.1__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.
- data_detective_toolkit-0.3.1/LICENSE +21 -0
- data_detective_toolkit-0.3.1/PKG-INFO +271 -0
- data_detective_toolkit-0.3.1/README.md +244 -0
- data_detective_toolkit-0.3.1/pyproject.toml +50 -0
- data_detective_toolkit-0.3.1/setup.cfg +4 -0
- data_detective_toolkit-0.3.1/src/data_detective/__init__.py +0 -0
- data_detective_toolkit-0.3.1/src/data_detective/cli.py +108 -0
- data_detective_toolkit-0.3.1/src/data_detective/exceptions.py +10 -0
- data_detective_toolkit-0.3.1/src/data_detective/html_report.py +730 -0
- data_detective_toolkit-0.3.1/src/data_detective/loader.py +52 -0
- data_detective_toolkit-0.3.1/src/data_detective/profiler.py +443 -0
- data_detective_toolkit-0.3.1/src/data_detective/report.py +57 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/PKG-INFO +271 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/SOURCES.txt +20 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/dependency_links.txt +1 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/entry_points.txt +2 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/requires.txt +10 -0
- data_detective_toolkit-0.3.1/src/data_detective_toolkit.egg-info/top_level.txt +1 -0
- data_detective_toolkit-0.3.1/tests/test_cli.py +103 -0
- data_detective_toolkit-0.3.1/tests/test_html_report.py +68 -0
- data_detective_toolkit-0.3.1/tests/test_loader.py +70 -0
- data_detective_toolkit-0.3.1/tests/test_profiler.py +219 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mursal Gorchuyev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: data-detective-toolkit
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Automated data-quality profiling: CLI, web app, and REST API for CSV intelligence reports.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/murs5l/data-detective
|
|
7
|
+
Project-URL: Issues, https://github.com/murs5l/data-detective/issues
|
|
8
|
+
Keywords: data-quality,profiling,csv,data-profiling,eda,outlier-detection
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: pandas<4.0,>=2.0
|
|
19
|
+
Requires-Dist: numpy<3.0,>=1.24
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
22
|
+
Provides-Extra: api
|
|
23
|
+
Requires-Dist: fastapi>=0.110; extra == "api"
|
|
24
|
+
Requires-Dist: uvicorn[standard]>=0.29; extra == "api"
|
|
25
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "api"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# 🕵️ Data Detective
|
|
29
|
+
|
|
30
|
+
[](https://github.com/murs5l/data-detective/actions/workflows/tests.yml)
|
|
31
|
+
|
|
32
|
+
**Automated data quality profiling in seconds.** Point Data Detective at a CSV and get back an intelligent report: shape, data types, missing values, duplicates, outliers, correlations, distribution skew, ID-like columns, and actionable insights. Choose your interface: fast CLI for scripts and CI, browser-based web app for exploration, or REST API for integration.
|
|
33
|
+
|
|
34
|
+
### Why Data Detective?
|
|
35
|
+
|
|
36
|
+
- **Fast**: profiles 1000+ rows in under a second
|
|
37
|
+
- **Thorough**: detects 20+ data quality issues (outliers, duplicates, high cardinality, mixed types, skew, etc.)
|
|
38
|
+
- **Private**: your data never leaves your machine; everything runs locally
|
|
39
|
+
- **Flexible**: use as a CLI tool, web app, Python library, or REST API
|
|
40
|
+
- **Lightweight**: no external ML services or cloud dependencies
|
|
41
|
+
|
|
42
|
+
### Two ways to use it
|
|
43
|
+
|
|
44
|
+
1. **CLI**: `data-detective analyze myfile.csv --html` for scripts and CI pipelines.
|
|
45
|
+
2. **Web app**: `docker compose up` for interactive exploration with live charts.
|
|
46
|
+
|
|
47
|
+
Both interfaces use the same profiling engine and produce identical reports.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Quick start
|
|
52
|
+
|
|
53
|
+
### Web app (interactive, no command line needed)
|
|
54
|
+
|
|
55
|
+
The easiest way to explore a CSV:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/murs5l/data-detective.git
|
|
59
|
+
cd data-detective
|
|
60
|
+
docker compose up --build
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then open **http://localhost:8000**, drag and drop a CSV, and explore. The report includes:
|
|
64
|
+
- Data shape and types
|
|
65
|
+
- Missing value heatmap
|
|
66
|
+
- Column Explorer: drill down into any numeric column to see histogram, boxplot, and 5-number summary
|
|
67
|
+
- Outlier detection (IQR and MAD methods)
|
|
68
|
+
- Correlation heatmap for numeric column pairs
|
|
69
|
+
- Insights highlighted in plain English
|
|
70
|
+
|
|
71
|
+
The browser-based UI is designed for non-technical and technical users alike: actionable insights appear first, and granular technical details are tucked behind a "Full technical report" toggle.
|
|
72
|
+
|
|
73
|
+
**Running without Docker:** if you have Python and FastAPI installed:
|
|
74
|
+
```bash
|
|
75
|
+
pip install -e ".[api]"
|
|
76
|
+
uvicorn backend.app.main:app --reload
|
|
77
|
+
```
|
|
78
|
+
Then visit `http://localhost:8000`.
|
|
79
|
+
|
|
80
|
+
### CLI (scripting and CI/CD)
|
|
81
|
+
|
|
82
|
+
Install locally for use in scripts and automated pipelines:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install data-detective-toolkit
|
|
86
|
+
data-detective analyze myfile.csv
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
> The PyPI package is `data-detective-toolkit`; the installed command is `data-detective`.
|
|
90
|
+
|
|
91
|
+
See [CLI docs](#cli) below for all flags and output formats.
|
|
92
|
+
|
|
93
|
+
## CLI reference
|
|
94
|
+
|
|
95
|
+
### Installation
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install data-detective-toolkit
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Basic usage
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Print a text summary to stdout
|
|
105
|
+
data-detective analyze myfile.csv
|
|
106
|
+
|
|
107
|
+
# Generate an interactive HTML report
|
|
108
|
+
data-detective analyze myfile.csv --html
|
|
109
|
+
|
|
110
|
+
# Output JSON for programmatic use
|
|
111
|
+
data-detective analyze myfile.csv --json | jq '.insights'
|
|
112
|
+
|
|
113
|
+
# Write to specific files
|
|
114
|
+
data-detective analyze myfile.csv --output-html reports/q1_data.html
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Options
|
|
118
|
+
|
|
119
|
+
| Flag | Description | Example |
|
|
120
|
+
|--------------------|-------------------------------------------------|---------|
|
|
121
|
+
| `--json` | Print full report as JSON to stdout | `data-detective analyze data.csv --json` |
|
|
122
|
+
| `--html` | Generate `report.html` in current directory | `data-detective analyze data.csv --html` |
|
|
123
|
+
| `--output-json` | Write JSON report to a specific file path | `--output-json reports/profile.json` |
|
|
124
|
+
| `--output-html` | Write HTML report to a specific file path | `--output-html reports/profile.html` |
|
|
125
|
+
| `--outlier-method` | Choose outlier detection: `iqr` or `mad` (default) | `--outlier-method iqr` |
|
|
126
|
+
| `--quiet` | Suppress non-error progress messages | `--quiet` |
|
|
127
|
+
|
|
128
|
+
### Examples
|
|
129
|
+
|
|
130
|
+
**CI/CD pipeline**: fail if data quality issues exceed a threshold
|
|
131
|
+
```bash
|
|
132
|
+
data-detective analyze incoming.csv --json | jq '.outliers_mad | length' | xargs -I {} bash -c 'exit {}'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Batch processing**: profile all CSVs in a directory
|
|
136
|
+
```bash
|
|
137
|
+
for f in data/*.csv; do
|
|
138
|
+
data-detective analyze "$f" --output-html "reports/$(basename $f .csv).html"
|
|
139
|
+
done
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Data validation**: check for specific issues before ETL
|
|
143
|
+
```bash
|
|
144
|
+
data-detective analyze input.csv --quiet --json | jq '.high_cardinality_columns'
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## REST API (for integration)
|
|
148
|
+
|
|
149
|
+
When running the web app or backend API server, you can integrate Data Detective into your own applications.
|
|
150
|
+
|
|
151
|
+
### Endpoints
|
|
152
|
+
|
|
153
|
+
**POST /api/analyze** – Analyze a CSV file, return JSON report
|
|
154
|
+
```bash
|
|
155
|
+
curl -F "file=@data.csv" "http://localhost:8000/api/analyze?outlier_method=mad"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Response: JSON object with all profiling data (see example below).
|
|
159
|
+
|
|
160
|
+
**POST /api/analyze/html** – Analyze a CSV file, return standalone HTML report
|
|
161
|
+
```bash
|
|
162
|
+
curl -F "file=@data.csv" "http://localhost:8000/api/analyze/html" > report.html
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Response: A self-contained HTML file (no external dependencies).
|
|
166
|
+
|
|
167
|
+
**GET /api/health** – Health check
|
|
168
|
+
```bash
|
|
169
|
+
curl http://localhost:8000/api/health
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Response: `{"status": "ok", "version": "0.3.0"}`
|
|
173
|
+
|
|
174
|
+
### Python example
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
import requests
|
|
178
|
+
|
|
179
|
+
with open("mydata.csv", "rb") as f:
|
|
180
|
+
response = requests.post(
|
|
181
|
+
"http://localhost:8000/api/analyze",
|
|
182
|
+
files={"file": f},
|
|
183
|
+
params={"outlier_method": "mad"}
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
report = response.json()
|
|
187
|
+
print(f"Shape: {report['shape']}")
|
|
188
|
+
print(f"Insights: {report['insights']}")
|
|
189
|
+
print(f"Outliers detected: {report['outliers_mad']}")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### JavaScript example
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
const formData = new FormData();
|
|
196
|
+
formData.append("file", csvFile); // File object from input[type=file]
|
|
197
|
+
|
|
198
|
+
const response = await fetch("/api/analyze?outlier_method=mad", {
|
|
199
|
+
method: "POST",
|
|
200
|
+
body: formData
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const report = await response.json();
|
|
204
|
+
console.log(report.insights);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Full API documentation is available at `/docs` (Swagger UI) when the backend is running.
|
|
208
|
+
|
|
209
|
+
## What it detects
|
|
210
|
+
|
|
211
|
+
Data Detective automatically flags 20+ data quality issues:
|
|
212
|
+
|
|
213
|
+
**Structure & Completeness**
|
|
214
|
+
- Shape (rows × columns) and column data types
|
|
215
|
+
- Missing values (count and percentage per column)
|
|
216
|
+
- Duplicate rows
|
|
217
|
+
- Duplicate columns (identical data, different names)
|
|
218
|
+
- Constant columns (no variation; e.g., all 1s)
|
|
219
|
+
|
|
220
|
+
**Statistical Issues**
|
|
221
|
+
- Outliers: IQR method (classic box-and-whisker) or MAD (robust for skewed data)
|
|
222
|
+
- Highly correlated numeric pairs
|
|
223
|
+
- Skewed distributions (heavy left/right tails)
|
|
224
|
+
- Kurtosis (fat tails or sharp peaks)
|
|
225
|
+
|
|
226
|
+
**Data Type & Value Issues**
|
|
227
|
+
- High-cardinality columns (likely IDs or keys)
|
|
228
|
+
- Mixed-type columns (e.g., numbers and strings in the same column)
|
|
229
|
+
- Unexpected negative values (e.g., negative `age`, `price`, `quantity`)
|
|
230
|
+
- Date-like values not parsed as datetime
|
|
231
|
+
|
|
232
|
+
**Text Columns**
|
|
233
|
+
- Length statistics (min, max, average)
|
|
234
|
+
- Blank or whitespace-only values
|
|
235
|
+
|
|
236
|
+
**Aggregates**
|
|
237
|
+
- Full numeric correlation matrix
|
|
238
|
+
- Histograms with bin edges and counts for numeric columns
|
|
239
|
+
- Five-number summary (min, Q1, median, Q3, max) per numeric column
|
|
240
|
+
- Per-column memory footprint (KB)
|
|
241
|
+
|
|
242
|
+
**Output**
|
|
243
|
+
- Plain-English actionable insights highlighting the most important issues
|
|
244
|
+
|
|
245
|
+
## Development
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# core engine + CLI
|
|
249
|
+
pip install -e ".[dev]"
|
|
250
|
+
pytest tests
|
|
251
|
+
|
|
252
|
+
# backend API
|
|
253
|
+
pip install -e ".[api]"
|
|
254
|
+
pip install -r backend/requirements-dev.txt
|
|
255
|
+
pytest backend/tests
|
|
256
|
+
|
|
257
|
+
# fastscan (Go speed layer)
|
|
258
|
+
cd tools/fastscan && go test ./...
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
CI runs all three (`.github/workflows/tests.yml`) on every push and PR.
|
|
262
|
+
|
|
263
|
+
## Roadmap
|
|
264
|
+
|
|
265
|
+
- GitHub Action to run Data Detective as a data-quality gate in CI
|
|
266
|
+
- Support for additional sources (Parquet, JSON, database connections)
|
|
267
|
+
- Scheduled/hosted profiling for pipelines beyond ad-hoc uploads
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# 🕵️ Data Detective
|
|
2
|
+
|
|
3
|
+
[](https://github.com/murs5l/data-detective/actions/workflows/tests.yml)
|
|
4
|
+
|
|
5
|
+
**Automated data quality profiling in seconds.** Point Data Detective at a CSV and get back an intelligent report: shape, data types, missing values, duplicates, outliers, correlations, distribution skew, ID-like columns, and actionable insights. Choose your interface: fast CLI for scripts and CI, browser-based web app for exploration, or REST API for integration.
|
|
6
|
+
|
|
7
|
+
### Why Data Detective?
|
|
8
|
+
|
|
9
|
+
- **Fast**: profiles 1000+ rows in under a second
|
|
10
|
+
- **Thorough**: detects 20+ data quality issues (outliers, duplicates, high cardinality, mixed types, skew, etc.)
|
|
11
|
+
- **Private**: your data never leaves your machine; everything runs locally
|
|
12
|
+
- **Flexible**: use as a CLI tool, web app, Python library, or REST API
|
|
13
|
+
- **Lightweight**: no external ML services or cloud dependencies
|
|
14
|
+
|
|
15
|
+
### Two ways to use it
|
|
16
|
+
|
|
17
|
+
1. **CLI**: `data-detective analyze myfile.csv --html` for scripts and CI pipelines.
|
|
18
|
+
2. **Web app**: `docker compose up` for interactive exploration with live charts.
|
|
19
|
+
|
|
20
|
+
Both interfaces use the same profiling engine and produce identical reports.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
### Web app (interactive, no command line needed)
|
|
27
|
+
|
|
28
|
+
The easiest way to explore a CSV:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/murs5l/data-detective.git
|
|
32
|
+
cd data-detective
|
|
33
|
+
docker compose up --build
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then open **http://localhost:8000**, drag and drop a CSV, and explore. The report includes:
|
|
37
|
+
- Data shape and types
|
|
38
|
+
- Missing value heatmap
|
|
39
|
+
- Column Explorer: drill down into any numeric column to see histogram, boxplot, and 5-number summary
|
|
40
|
+
- Outlier detection (IQR and MAD methods)
|
|
41
|
+
- Correlation heatmap for numeric column pairs
|
|
42
|
+
- Insights highlighted in plain English
|
|
43
|
+
|
|
44
|
+
The browser-based UI is designed for non-technical and technical users alike: actionable insights appear first, and granular technical details are tucked behind a "Full technical report" toggle.
|
|
45
|
+
|
|
46
|
+
**Running without Docker:** if you have Python and FastAPI installed:
|
|
47
|
+
```bash
|
|
48
|
+
pip install -e ".[api]"
|
|
49
|
+
uvicorn backend.app.main:app --reload
|
|
50
|
+
```
|
|
51
|
+
Then visit `http://localhost:8000`.
|
|
52
|
+
|
|
53
|
+
### CLI (scripting and CI/CD)
|
|
54
|
+
|
|
55
|
+
Install locally for use in scripts and automated pipelines:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install data-detective-toolkit
|
|
59
|
+
data-detective analyze myfile.csv
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> The PyPI package is `data-detective-toolkit`; the installed command is `data-detective`.
|
|
63
|
+
|
|
64
|
+
See [CLI docs](#cli) below for all flags and output formats.
|
|
65
|
+
|
|
66
|
+
## CLI reference
|
|
67
|
+
|
|
68
|
+
### Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install data-detective-toolkit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Basic usage
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Print a text summary to stdout
|
|
78
|
+
data-detective analyze myfile.csv
|
|
79
|
+
|
|
80
|
+
# Generate an interactive HTML report
|
|
81
|
+
data-detective analyze myfile.csv --html
|
|
82
|
+
|
|
83
|
+
# Output JSON for programmatic use
|
|
84
|
+
data-detective analyze myfile.csv --json | jq '.insights'
|
|
85
|
+
|
|
86
|
+
# Write to specific files
|
|
87
|
+
data-detective analyze myfile.csv --output-html reports/q1_data.html
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Options
|
|
91
|
+
|
|
92
|
+
| Flag | Description | Example |
|
|
93
|
+
|--------------------|-------------------------------------------------|---------|
|
|
94
|
+
| `--json` | Print full report as JSON to stdout | `data-detective analyze data.csv --json` |
|
|
95
|
+
| `--html` | Generate `report.html` in current directory | `data-detective analyze data.csv --html` |
|
|
96
|
+
| `--output-json` | Write JSON report to a specific file path | `--output-json reports/profile.json` |
|
|
97
|
+
| `--output-html` | Write HTML report to a specific file path | `--output-html reports/profile.html` |
|
|
98
|
+
| `--outlier-method` | Choose outlier detection: `iqr` or `mad` (default) | `--outlier-method iqr` |
|
|
99
|
+
| `--quiet` | Suppress non-error progress messages | `--quiet` |
|
|
100
|
+
|
|
101
|
+
### Examples
|
|
102
|
+
|
|
103
|
+
**CI/CD pipeline**: fail if data quality issues exceed a threshold
|
|
104
|
+
```bash
|
|
105
|
+
data-detective analyze incoming.csv --json | jq '.outliers_mad | length' | xargs -I {} bash -c 'exit {}'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Batch processing**: profile all CSVs in a directory
|
|
109
|
+
```bash
|
|
110
|
+
for f in data/*.csv; do
|
|
111
|
+
data-detective analyze "$f" --output-html "reports/$(basename $f .csv).html"
|
|
112
|
+
done
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Data validation**: check for specific issues before ETL
|
|
116
|
+
```bash
|
|
117
|
+
data-detective analyze input.csv --quiet --json | jq '.high_cardinality_columns'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## REST API (for integration)
|
|
121
|
+
|
|
122
|
+
When running the web app or backend API server, you can integrate Data Detective into your own applications.
|
|
123
|
+
|
|
124
|
+
### Endpoints
|
|
125
|
+
|
|
126
|
+
**POST /api/analyze** – Analyze a CSV file, return JSON report
|
|
127
|
+
```bash
|
|
128
|
+
curl -F "file=@data.csv" "http://localhost:8000/api/analyze?outlier_method=mad"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Response: JSON object with all profiling data (see example below).
|
|
132
|
+
|
|
133
|
+
**POST /api/analyze/html** – Analyze a CSV file, return standalone HTML report
|
|
134
|
+
```bash
|
|
135
|
+
curl -F "file=@data.csv" "http://localhost:8000/api/analyze/html" > report.html
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Response: A self-contained HTML file (no external dependencies).
|
|
139
|
+
|
|
140
|
+
**GET /api/health** – Health check
|
|
141
|
+
```bash
|
|
142
|
+
curl http://localhost:8000/api/health
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Response: `{"status": "ok", "version": "0.3.0"}`
|
|
146
|
+
|
|
147
|
+
### Python example
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
import requests
|
|
151
|
+
|
|
152
|
+
with open("mydata.csv", "rb") as f:
|
|
153
|
+
response = requests.post(
|
|
154
|
+
"http://localhost:8000/api/analyze",
|
|
155
|
+
files={"file": f},
|
|
156
|
+
params={"outlier_method": "mad"}
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
report = response.json()
|
|
160
|
+
print(f"Shape: {report['shape']}")
|
|
161
|
+
print(f"Insights: {report['insights']}")
|
|
162
|
+
print(f"Outliers detected: {report['outliers_mad']}")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### JavaScript example
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
const formData = new FormData();
|
|
169
|
+
formData.append("file", csvFile); // File object from input[type=file]
|
|
170
|
+
|
|
171
|
+
const response = await fetch("/api/analyze?outlier_method=mad", {
|
|
172
|
+
method: "POST",
|
|
173
|
+
body: formData
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
const report = await response.json();
|
|
177
|
+
console.log(report.insights);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Full API documentation is available at `/docs` (Swagger UI) when the backend is running.
|
|
181
|
+
|
|
182
|
+
## What it detects
|
|
183
|
+
|
|
184
|
+
Data Detective automatically flags 20+ data quality issues:
|
|
185
|
+
|
|
186
|
+
**Structure & Completeness**
|
|
187
|
+
- Shape (rows × columns) and column data types
|
|
188
|
+
- Missing values (count and percentage per column)
|
|
189
|
+
- Duplicate rows
|
|
190
|
+
- Duplicate columns (identical data, different names)
|
|
191
|
+
- Constant columns (no variation; e.g., all 1s)
|
|
192
|
+
|
|
193
|
+
**Statistical Issues**
|
|
194
|
+
- Outliers: IQR method (classic box-and-whisker) or MAD (robust for skewed data)
|
|
195
|
+
- Highly correlated numeric pairs
|
|
196
|
+
- Skewed distributions (heavy left/right tails)
|
|
197
|
+
- Kurtosis (fat tails or sharp peaks)
|
|
198
|
+
|
|
199
|
+
**Data Type & Value Issues**
|
|
200
|
+
- High-cardinality columns (likely IDs or keys)
|
|
201
|
+
- Mixed-type columns (e.g., numbers and strings in the same column)
|
|
202
|
+
- Unexpected negative values (e.g., negative `age`, `price`, `quantity`)
|
|
203
|
+
- Date-like values not parsed as datetime
|
|
204
|
+
|
|
205
|
+
**Text Columns**
|
|
206
|
+
- Length statistics (min, max, average)
|
|
207
|
+
- Blank or whitespace-only values
|
|
208
|
+
|
|
209
|
+
**Aggregates**
|
|
210
|
+
- Full numeric correlation matrix
|
|
211
|
+
- Histograms with bin edges and counts for numeric columns
|
|
212
|
+
- Five-number summary (min, Q1, median, Q3, max) per numeric column
|
|
213
|
+
- Per-column memory footprint (KB)
|
|
214
|
+
|
|
215
|
+
**Output**
|
|
216
|
+
- Plain-English actionable insights highlighting the most important issues
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# core engine + CLI
|
|
222
|
+
pip install -e ".[dev]"
|
|
223
|
+
pytest tests
|
|
224
|
+
|
|
225
|
+
# backend API
|
|
226
|
+
pip install -e ".[api]"
|
|
227
|
+
pip install -r backend/requirements-dev.txt
|
|
228
|
+
pytest backend/tests
|
|
229
|
+
|
|
230
|
+
# fastscan (Go speed layer)
|
|
231
|
+
cd tools/fastscan && go test ./...
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
CI runs all three (`.github/workflows/tests.yml`) on every push and PR.
|
|
235
|
+
|
|
236
|
+
## Roadmap
|
|
237
|
+
|
|
238
|
+
- GitHub Action to run Data Detective as a data-quality gate in CI
|
|
239
|
+
- Support for additional sources (Parquet, JSON, database connections)
|
|
240
|
+
- Scheduled/hosted profiling for pipelines beyond ad-hoc uploads
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "data-detective-toolkit"
|
|
7
|
+
version = "0.3.1"
|
|
8
|
+
description = "Automated data-quality profiling: CLI, web app, and REST API for CSV intelligence reports."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
keywords = ["data-quality", "profiling", "csv", "data-profiling", "eda", "outlier-detection"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
19
|
+
"Topic :: Utilities",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
# Upper bounds are intentional: CI has verified compatibility up to
|
|
23
|
+
# pandas 3.x (Python 3.11/3.12 already resolve to it), but the next
|
|
24
|
+
# major bump should be a deliberate version-bump PR, not a silent
|
|
25
|
+
# `pip install` picking up unverified breaking changes.
|
|
26
|
+
"pandas>=2.0,<4.0",
|
|
27
|
+
"numpy>=1.24,<3.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = ["pytest>=7.0"]
|
|
32
|
+
api = [
|
|
33
|
+
"fastapi>=0.110",
|
|
34
|
+
"uvicorn[standard]>=0.29",
|
|
35
|
+
"python-multipart>=0.0.9",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[tool.setuptools]
|
|
39
|
+
package-dir = {"" = "src"}
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
where = ["src"]
|
|
43
|
+
include = ["data_detective*"]
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
data-detective = "data_detective.cli:main"
|
|
47
|
+
|
|
48
|
+
[project.urls]
|
|
49
|
+
Homepage = "https://github.com/murs5l/data-detective"
|
|
50
|
+
Issues = "https://github.com/murs5l/data-detective/issues"
|
|
File without changes
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from data_detective.exceptions import DataLoadError
|
|
7
|
+
from data_detective.html_report import generate_html_report
|
|
8
|
+
from data_detective.loader import load_csv
|
|
9
|
+
from data_detective.profiler import DataProfiler
|
|
10
|
+
from data_detective.report import print_report
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# -----------------------------
|
|
14
|
+
# COMMAND HANDLER
|
|
15
|
+
# -----------------------------
|
|
16
|
+
def run_analyze(args):
|
|
17
|
+
if not args.quiet:
|
|
18
|
+
print("🔥 Data Detective starting...\n")
|
|
19
|
+
|
|
20
|
+
df = load_csv(args.file)
|
|
21
|
+
profiler = DataProfiler(df)
|
|
22
|
+
report = profiler.run_full_profile(outlier_method=args.outlier_method)
|
|
23
|
+
|
|
24
|
+
emit_html = args.html or bool(args.output_html)
|
|
25
|
+
emit_json = args.json or bool(args.output_json)
|
|
26
|
+
|
|
27
|
+
if emit_html:
|
|
28
|
+
output_html_path = args.output_html or "report.html"
|
|
29
|
+
generate_html_report(report, output_path=output_html_path)
|
|
30
|
+
|
|
31
|
+
if emit_json:
|
|
32
|
+
payload = json.dumps(report, indent=2)
|
|
33
|
+
if args.output_json:
|
|
34
|
+
Path(args.output_json).write_text(payload + "\n", encoding="utf-8")
|
|
35
|
+
elif args.json:
|
|
36
|
+
print(payload)
|
|
37
|
+
|
|
38
|
+
if emit_html or emit_json:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
if not args.json and not args.html:
|
|
42
|
+
print_report(report)
|
|
43
|
+
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# -----------------------------
|
|
48
|
+
# CLI SETUP
|
|
49
|
+
# -----------------------------
|
|
50
|
+
def build_parser():
|
|
51
|
+
parser = argparse.ArgumentParser(
|
|
52
|
+
prog="data-detective",
|
|
53
|
+
description="🕵️ Data Detective - Smart Data Profiling Tool"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
57
|
+
|
|
58
|
+
analyze_parser = subparsers.add_parser(
|
|
59
|
+
"analyze",
|
|
60
|
+
help="Analyze a CSV file"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
analyze_parser.add_argument("file", help="Path to CSV file")
|
|
64
|
+
analyze_parser.add_argument("--json", action="store_true", help="Output JSON report")
|
|
65
|
+
analyze_parser.add_argument("--html", action="store_true", help="Generate HTML report")
|
|
66
|
+
analyze_parser.add_argument("--output-json", help="Write JSON report to the given file path")
|
|
67
|
+
analyze_parser.add_argument("--output-html", help="Write HTML report to the given file path")
|
|
68
|
+
analyze_parser.add_argument(
|
|
69
|
+
"--outlier-method",
|
|
70
|
+
choices=["iqr", "mad"],
|
|
71
|
+
default="mad",
|
|
72
|
+
help="Outlier detection method used for insights (default: mad)",
|
|
73
|
+
)
|
|
74
|
+
analyze_parser.add_argument(
|
|
75
|
+
"--quiet",
|
|
76
|
+
action="store_true",
|
|
77
|
+
help="Suppress non-error progress messages",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
analyze_parser.set_defaults(func=run_analyze)
|
|
81
|
+
|
|
82
|
+
return parser
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# -----------------------------
|
|
86
|
+
# MAIN ENTRY POINT
|
|
87
|
+
# -----------------------------
|
|
88
|
+
def main():
|
|
89
|
+
parser = build_parser()
|
|
90
|
+
args = parser.parse_args()
|
|
91
|
+
|
|
92
|
+
if not hasattr(args, "func"):
|
|
93
|
+
parser.print_help()
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
return args.func(args)
|
|
98
|
+
except DataLoadError as e:
|
|
99
|
+
print(f"❌ {e}", file=sys.stderr)
|
|
100
|
+
return 1
|
|
101
|
+
except Exception as e:
|
|
102
|
+
print(f"❌ Unexpected error: {e}", file=sys.stderr)
|
|
103
|
+
return 1
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# REQUIRED ENTRY POINT
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
sys.exit(main())
|