balancr 0.1.0__py3-none-any.whl
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.
- balancr/__init__.py +13 -0
- balancr/base.py +14 -0
- balancr/classifier_registry.py +300 -0
- balancr/cli/__init__.py +0 -0
- balancr/cli/commands.py +1838 -0
- balancr/cli/config.py +165 -0
- balancr/cli/main.py +778 -0
- balancr/cli/utils.py +101 -0
- balancr/data/__init__.py +5 -0
- balancr/data/loader.py +59 -0
- balancr/data/preprocessor.py +556 -0
- balancr/evaluation/__init__.py +19 -0
- balancr/evaluation/metrics.py +442 -0
- balancr/evaluation/visualisation.py +660 -0
- balancr/imbalance_analyser.py +677 -0
- balancr/technique_registry.py +284 -0
- balancr/techniques/__init__.py +4 -0
- balancr/techniques/custom/__init__.py +0 -0
- balancr/techniques/custom/example_custom_technique.py +27 -0
- balancr-0.1.0.dist-info/LICENSE +21 -0
- balancr-0.1.0.dist-info/METADATA +536 -0
- balancr-0.1.0.dist-info/RECORD +25 -0
- balancr-0.1.0.dist-info/WHEEL +5 -0
- balancr-0.1.0.dist-info/entry_points.txt +2 -0
- balancr-0.1.0.dist-info/top_level.txt +1 -0
balancr/cli/config.py
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
"""
|
2
|
+
config.py - Configuration management for the balancr CLI.
|
3
|
+
|
4
|
+
This module handles loading, saving, and updating the configuration
|
5
|
+
file that stores user settings between command executions.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import json
|
9
|
+
import logging
|
10
|
+
from pathlib import Path
|
11
|
+
|
12
|
+
|
13
|
+
def initialise_config(config_path: str, force: bool = False) -> None:
|
14
|
+
"""
|
15
|
+
Initialise a new configuration file with default settings.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
config_path: Path to the configuration file
|
19
|
+
force: Whether to overwrite an existing file
|
20
|
+
|
21
|
+
Raises:
|
22
|
+
IOError: If the file exists and force is False
|
23
|
+
"""
|
24
|
+
config_path = Path(config_path)
|
25
|
+
|
26
|
+
# Check if file already exists
|
27
|
+
if config_path.exists() and not force:
|
28
|
+
logging.info(f"Configuration file already exists at {config_path}")
|
29
|
+
return
|
30
|
+
|
31
|
+
# Create default configuration
|
32
|
+
default_config = {
|
33
|
+
"preprocessing": {
|
34
|
+
"handle_missing": "mean",
|
35
|
+
"scale": "standard",
|
36
|
+
"encode": "auto",
|
37
|
+
},
|
38
|
+
"evaluation": {
|
39
|
+
"test_size": 0.2,
|
40
|
+
"cross_validation": 0,
|
41
|
+
"random_state": 42,
|
42
|
+
"learning_curve_folds": 5,
|
43
|
+
"learning_curve_points": 10
|
44
|
+
},
|
45
|
+
"output": {
|
46
|
+
"metrics": ["precision", "recall", "f1", "roc_auc"],
|
47
|
+
"visualisations": ["all"],
|
48
|
+
"display_visualisations": False,
|
49
|
+
"save_metrics_formats": ["csv"],
|
50
|
+
"save_vis_formats": ["png"],
|
51
|
+
},
|
52
|
+
}
|
53
|
+
|
54
|
+
# Ensure directory exists
|
55
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
56
|
+
|
57
|
+
# Write configuration file
|
58
|
+
with open(config_path, "w") as f:
|
59
|
+
json.dump(default_config, f, indent=2)
|
60
|
+
|
61
|
+
logging.info(f"Initialised configuration file at {config_path}")
|
62
|
+
|
63
|
+
|
64
|
+
def load_config(config_path: str) -> dict:
|
65
|
+
"""
|
66
|
+
Load configuration from file.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
config_path: Path to the configuration file
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
Dictionary containing configuration
|
73
|
+
|
74
|
+
Raises:
|
75
|
+
FileNotFoundError: If config file doesn't exist
|
76
|
+
json.JSONDecodeError: If config file is invalid JSON
|
77
|
+
"""
|
78
|
+
config_path = Path(config_path)
|
79
|
+
|
80
|
+
if not config_path.exists():
|
81
|
+
raise FileNotFoundError(f"Configuration file not found at {config_path}")
|
82
|
+
|
83
|
+
with open(config_path, "r") as f:
|
84
|
+
config = json.load(f)
|
85
|
+
|
86
|
+
return config
|
87
|
+
|
88
|
+
|
89
|
+
def update_config(config_path: str, settings: dict) -> None:
|
90
|
+
"""
|
91
|
+
Update existing configuration with new settings.
|
92
|
+
|
93
|
+
Args:
|
94
|
+
config_path: Path to the configuration file
|
95
|
+
settings: Dictionary containing settings to update
|
96
|
+
|
97
|
+
Raises:
|
98
|
+
FileNotFoundError: If config file doesn't exist
|
99
|
+
"""
|
100
|
+
config_path = Path(config_path)
|
101
|
+
|
102
|
+
# Load existing config
|
103
|
+
try:
|
104
|
+
current_config = load_config(config_path)
|
105
|
+
except FileNotFoundError:
|
106
|
+
# Initialise if it doesn't exist
|
107
|
+
initialise_config(config_path)
|
108
|
+
current_config = load_config(config_path)
|
109
|
+
|
110
|
+
# Update configuration recursively
|
111
|
+
deep_update(current_config, settings)
|
112
|
+
|
113
|
+
# Write updated configuration
|
114
|
+
with open(config_path, "w") as f:
|
115
|
+
json.dump(current_config, f, indent=2)
|
116
|
+
|
117
|
+
logging.debug(f"Updated configuration at {config_path}")
|
118
|
+
|
119
|
+
|
120
|
+
def deep_update(original: dict, update: dict) -> dict:
|
121
|
+
"""
|
122
|
+
Recursively update a dictionary.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
original: Dictionary to update
|
126
|
+
update: Dictionary with updates
|
127
|
+
|
128
|
+
Returns:
|
129
|
+
The updated original dictionary
|
130
|
+
"""
|
131
|
+
for key, value in update.items():
|
132
|
+
if (
|
133
|
+
isinstance(value, dict)
|
134
|
+
and key in original
|
135
|
+
and isinstance(original[key], dict)
|
136
|
+
):
|
137
|
+
# Recursively update nested dictionaries
|
138
|
+
deep_update(original[key], value)
|
139
|
+
else:
|
140
|
+
# Update or add values
|
141
|
+
original[key] = value
|
142
|
+
|
143
|
+
return original
|
144
|
+
|
145
|
+
|
146
|
+
def print_config(config_path: str) -> int:
|
147
|
+
"""
|
148
|
+
Print the current configuration.
|
149
|
+
|
150
|
+
Args:
|
151
|
+
config_path: Path to the configuration file
|
152
|
+
|
153
|
+
Returns:
|
154
|
+
Exit code
|
155
|
+
"""
|
156
|
+
try:
|
157
|
+
config = load_config(config_path)
|
158
|
+
|
159
|
+
print("\nCurrent Configuration:")
|
160
|
+
print(json.dumps(config, indent=2))
|
161
|
+
|
162
|
+
return 0
|
163
|
+
except Exception as e:
|
164
|
+
logging.error(f"Error reading configuration: {e}")
|
165
|
+
return 1
|