plot-misc 2.1.0__tar.gz → 2.2.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.
- {plot_misc-2.1.0/plot_misc.egg-info → plot_misc-2.2.1}/PKG-INFO +75 -19
- {plot_misc-2.1.0 → plot_misc-2.2.1}/README.md +63 -17
- plot_misc-2.2.1/plot_misc/_version.py +1 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/barchart.py +72 -30
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/constants.py +4 -4
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/errors.py +6 -6
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/examples.py +233 -1
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/forest.py +55 -55
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/heatmap.py +18 -141
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/incidencematrix.py +38 -28
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/machine_learning.py +35 -35
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/piechart.py +10 -10
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/survival.py +10 -11
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/utils/colour.py +1 -17
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/utils/formatting.py +10 -13
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/utils/utils.py +29 -30
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/volcano.py +38 -24
- {plot_misc-2.1.0 → plot_misc-2.2.1/plot_misc.egg-info}/PKG-INFO +75 -19
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc.egg-info/SOURCES.txt +0 -1
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc.egg-info/requires.txt +11 -1
- {plot_misc-2.1.0 → plot_misc-2.2.1}/pyproject.toml +1 -1
- plot_misc-2.2.1/requirements-dev.txt +20 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/requirements.txt +0 -1
- plot_misc-2.1.0/plot_misc/_version.py +0 -1
- plot_misc-2.1.0/plot_misc/example_data/example_datasets/string_data.txt +0 -1
- plot_misc-2.1.0/requirements-dev.txt +0 -9
- {plot_misc-2.1.0 → plot_misc-2.2.1}/LICENSE +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/MANIFEST.in +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/__init__.py +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/__init__.py +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/bar_points.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/barchart.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/calibration_bins.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/calibration_data.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/forest_data.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/group_bar.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/heatmap_data.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/incidence_matrix_data.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/lollipop_data.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/mace_associations.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/net_benefit.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/example_data/example_datasets/volcano.tsv.gz +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc/utils/__init__.py +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc.egg-info/dependency_links.txt +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/plot_misc.egg-info/top_level.txt +0 -0
- {plot_misc-2.1.0 → plot_misc-2.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plot-misc
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: Various plotting templates built on top of matplotlib
|
|
5
5
|
Author-email: A Floriaan Schmidt <floriaanschmidt@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -18,7 +18,6 @@ License-File: LICENSE
|
|
|
18
18
|
Requires-Dist: pandas>=1.3
|
|
19
19
|
Requires-Dist: numpy>=1.21
|
|
20
20
|
Requires-Dist: matplotlib>=3.5
|
|
21
|
-
Requires-Dist: seaborn>=0.11
|
|
22
21
|
Requires-Dist: scipy>=1.5
|
|
23
22
|
Requires-Dist: statsmodels>=0.1
|
|
24
23
|
Requires-Dist: scikit-learn>=1.4
|
|
@@ -32,13 +31,24 @@ Requires-Dist: pytest>=6; extra == "dev"
|
|
|
32
31
|
Requires-Dist: pytest-mock>=3; extra == "dev"
|
|
33
32
|
Requires-Dist: pytest-dependency>=0.5; extra == "dev"
|
|
34
33
|
Requires-Dist: bump2version>=1; extra == "dev"
|
|
34
|
+
Requires-Dist: codespell; extra == "dev"
|
|
35
35
|
Requires-Dist: jupyter; extra == "dev"
|
|
36
|
+
Requires-Dist: sphinx_rtd_theme; extra == "dev"
|
|
37
|
+
Requires-Dist: sphinx-bootstrap-theme; extra == "dev"
|
|
38
|
+
Requires-Dist: furo; extra == "dev"
|
|
39
|
+
Requires-Dist: myst-parser; extra == "dev"
|
|
40
|
+
Requires-Dist: notebook; extra == "dev"
|
|
41
|
+
Requires-Dist: nbsphinx; extra == "dev"
|
|
42
|
+
Requires-Dist: nbsphinx-link; extra == "dev"
|
|
43
|
+
Requires-Dist: sphinx-argparse; extra == "dev"
|
|
44
|
+
Requires-Dist: numpydoc; extra == "dev"
|
|
45
|
+
Requires-Dist: docutils<0.21; extra == "dev"
|
|
36
46
|
Dynamic: license-file
|
|
37
47
|
|
|
38
48
|
<img src="https://schmidtaf.gitlab.io/plot-misc/_images/icon.png" alt="plot-misc icon" width="250"/>
|
|
39
49
|
|
|
40
50
|
# A collection of plotting functions
|
|
41
|
-
__version__: `2.1
|
|
51
|
+
__version__: `2.2.1`
|
|
42
52
|
|
|
43
53
|
This repository collects plotting modules written on top of `matplotlib`.
|
|
44
54
|
The functions are intended to set up light-touch, basic illustrations that
|
|
@@ -48,7 +58,8 @@ covering forest plots, volcano plots, incidence matrices/bubble charts,
|
|
|
48
58
|
illustrations to evaluate prediction models (e.g. feature importance, net benefit, calibration plots),
|
|
49
59
|
and more.
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
Please consult the **[documentation](https://SchmidtAF.gitlab.io/plot-misc/)**
|
|
62
|
+
for plot-misc.
|
|
52
63
|
|
|
53
64
|
## Installation
|
|
54
65
|
The package is available on PyPI, and conda, with the latest source code
|
|
@@ -58,7 +69,7 @@ available on gitlab.
|
|
|
58
69
|
|
|
59
70
|
To install the package from PyPI, run:
|
|
60
71
|
|
|
61
|
-
```
|
|
72
|
+
```bash
|
|
62
73
|
pip install plot-misc
|
|
63
74
|
```
|
|
64
75
|
|
|
@@ -69,50 +80,94 @@ This installs the latest stable release along with its dependencies.
|
|
|
69
80
|
A Conda package is maintained in my personal Conda channel.
|
|
70
81
|
To install from this channel, run:
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
```sh
|
|
83
|
+
```bash
|
|
74
84
|
conda install afschmidt::plot-misc
|
|
75
85
|
```
|
|
76
86
|
|
|
77
87
|
### Installation using gitlab
|
|
78
88
|
|
|
79
|
-
If you require the latest updates, potentially not yet formally released,
|
|
89
|
+
If you require the latest updates, potentially not yet formally released,
|
|
90
|
+
you can install the package directly from GitLab.
|
|
80
91
|
|
|
81
92
|
First, clone the repository and move into its root directory:
|
|
82
93
|
|
|
83
|
-
```
|
|
94
|
+
```bash
|
|
84
95
|
git clone git@gitlab.com:SchmidtAF/plot-misc.git
|
|
85
96
|
cd plot-misc
|
|
86
97
|
```
|
|
87
98
|
|
|
88
99
|
Install the dependencies:
|
|
89
100
|
|
|
90
|
-
```
|
|
101
|
+
```bash
|
|
91
102
|
# From the root of the repository
|
|
92
103
|
conda env create --file ./resources/conda/envs/conda_create.yaml
|
|
93
104
|
```
|
|
94
105
|
|
|
95
106
|
To add to an existing environment use:
|
|
96
107
|
|
|
97
|
-
```
|
|
108
|
+
```bash
|
|
98
109
|
# From the root of the repository
|
|
99
110
|
conda env update --file ./resources/conda/envs/conda_update.yaml
|
|
100
111
|
```
|
|
101
112
|
|
|
102
113
|
Next the package can be installed:
|
|
103
114
|
|
|
104
|
-
```
|
|
105
|
-
|
|
115
|
+
```bash
|
|
116
|
+
make install
|
|
106
117
|
```
|
|
107
118
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
#### Development
|
|
120
|
+
For development work, install the package in editable mode with Git commit
|
|
121
|
+
hooks configured:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
make install-dev
|
|
125
|
+
```
|
|
126
|
+
This command installs the package in editable mode and configures Git commit
|
|
127
|
+
hooks, allowing you to run `git pull` to update the repository or switch
|
|
128
|
+
branches without reinstalling.
|
|
112
129
|
|
|
113
|
-
|
|
130
|
+
Alternatively, you can install manually:
|
|
131
|
+
```bash
|
|
114
132
|
python -m pip install -e .
|
|
133
|
+
python .setup_git_hooks.py
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Git Hooks Configuration
|
|
137
|
+
|
|
115
138
|
|
|
139
|
+
When setting up a development environment, the `setup-hooks` command
|
|
140
|
+
configures Git hooks to enforce conventional commit message formatting and
|
|
141
|
+
spell check using `codespell`.
|
|
142
|
+
|
|
143
|
+
To view the commit message format requirements, run:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
./.githooks/commit-msg -help
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For frequent use, add this function to your shell configuration (`~/.bashrc`
|
|
150
|
+
or `~/.zshrc`):
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
commit-format-help() {
|
|
154
|
+
local git_root
|
|
155
|
+
git_root=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
156
|
+
|
|
157
|
+
if [ -z "$git_root" ]; then
|
|
158
|
+
echo "Error: Not inside a git repository"
|
|
159
|
+
return 1
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
local hook_path="$git_root/.githooks/commit-msg"
|
|
163
|
+
|
|
164
|
+
if [ ! -f "$hook_path" ]; then
|
|
165
|
+
echo "Error: commit-msg hook not found"
|
|
166
|
+
return 1
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
"$hook_path" --help
|
|
170
|
+
}
|
|
116
171
|
```
|
|
117
172
|
|
|
118
173
|
#### Validating the package
|
|
@@ -120,7 +175,7 @@ python -m pip install -e .
|
|
|
120
175
|
After installing the package from GitLab, you may wish to run the test
|
|
121
176
|
suite to confirm everything is working as expected:
|
|
122
177
|
|
|
123
|
-
```
|
|
178
|
+
```bash
|
|
124
179
|
# From the root of the repository
|
|
125
180
|
pytest tests
|
|
126
181
|
```
|
|
@@ -131,3 +186,4 @@ Please have a look at the examples in
|
|
|
131
186
|
[resources](https://gitlab.com/SchmidtAF/plot-misc/-/tree/master/resources/examples)
|
|
132
187
|
for some possible recipes.
|
|
133
188
|
|
|
189
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<img src="https://schmidtaf.gitlab.io/plot-misc/_images/icon.png" alt="plot-misc icon" width="250"/>
|
|
2
2
|
|
|
3
3
|
# A collection of plotting functions
|
|
4
|
-
__version__: `2.1
|
|
4
|
+
__version__: `2.2.1`
|
|
5
5
|
|
|
6
6
|
This repository collects plotting modules written on top of `matplotlib`.
|
|
7
7
|
The functions are intended to set up light-touch, basic illustrations that
|
|
@@ -11,7 +11,8 @@ covering forest plots, volcano plots, incidence matrices/bubble charts,
|
|
|
11
11
|
illustrations to evaluate prediction models (e.g. feature importance, net benefit, calibration plots),
|
|
12
12
|
and more.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
Please consult the **[documentation](https://SchmidtAF.gitlab.io/plot-misc/)**
|
|
15
|
+
for plot-misc.
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
The package is available on PyPI, and conda, with the latest source code
|
|
@@ -21,7 +22,7 @@ available on gitlab.
|
|
|
21
22
|
|
|
22
23
|
To install the package from PyPI, run:
|
|
23
24
|
|
|
24
|
-
```
|
|
25
|
+
```bash
|
|
25
26
|
pip install plot-misc
|
|
26
27
|
```
|
|
27
28
|
|
|
@@ -32,50 +33,94 @@ This installs the latest stable release along with its dependencies.
|
|
|
32
33
|
A Conda package is maintained in my personal Conda channel.
|
|
33
34
|
To install from this channel, run:
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
```sh
|
|
36
|
+
```bash
|
|
37
37
|
conda install afschmidt::plot-misc
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
### Installation using gitlab
|
|
41
41
|
|
|
42
|
-
If you require the latest updates, potentially not yet formally released,
|
|
42
|
+
If you require the latest updates, potentially not yet formally released,
|
|
43
|
+
you can install the package directly from GitLab.
|
|
43
44
|
|
|
44
45
|
First, clone the repository and move into its root directory:
|
|
45
46
|
|
|
46
|
-
```
|
|
47
|
+
```bash
|
|
47
48
|
git clone git@gitlab.com:SchmidtAF/plot-misc.git
|
|
48
49
|
cd plot-misc
|
|
49
50
|
```
|
|
50
51
|
|
|
51
52
|
Install the dependencies:
|
|
52
53
|
|
|
53
|
-
```
|
|
54
|
+
```bash
|
|
54
55
|
# From the root of the repository
|
|
55
56
|
conda env create --file ./resources/conda/envs/conda_create.yaml
|
|
56
57
|
```
|
|
57
58
|
|
|
58
59
|
To add to an existing environment use:
|
|
59
60
|
|
|
60
|
-
```
|
|
61
|
+
```bash
|
|
61
62
|
# From the root of the repository
|
|
62
63
|
conda env update --file ./resources/conda/envs/conda_update.yaml
|
|
63
64
|
```
|
|
64
65
|
|
|
65
66
|
Next the package can be installed:
|
|
66
67
|
|
|
67
|
-
```
|
|
68
|
-
|
|
68
|
+
```bash
|
|
69
|
+
make install
|
|
69
70
|
```
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
#### Development
|
|
73
|
+
For development work, install the package in editable mode with Git commit
|
|
74
|
+
hooks configured:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
make install-dev
|
|
78
|
+
```
|
|
79
|
+
This command installs the package in editable mode and configures Git commit
|
|
80
|
+
hooks, allowing you to run `git pull` to update the repository or switch
|
|
81
|
+
branches without reinstalling.
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
Alternatively, you can install manually:
|
|
84
|
+
```bash
|
|
77
85
|
python -m pip install -e .
|
|
86
|
+
python .setup_git_hooks.py
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Git Hooks Configuration
|
|
90
|
+
|
|
78
91
|
|
|
92
|
+
When setting up a development environment, the `setup-hooks` command
|
|
93
|
+
configures Git hooks to enforce conventional commit message formatting and
|
|
94
|
+
spell check using `codespell`.
|
|
95
|
+
|
|
96
|
+
To view the commit message format requirements, run:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
./.githooks/commit-msg -help
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For frequent use, add this function to your shell configuration (`~/.bashrc`
|
|
103
|
+
or `~/.zshrc`):
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
commit-format-help() {
|
|
107
|
+
local git_root
|
|
108
|
+
git_root=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
109
|
+
|
|
110
|
+
if [ -z "$git_root" ]; then
|
|
111
|
+
echo "Error: Not inside a git repository"
|
|
112
|
+
return 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
local hook_path="$git_root/.githooks/commit-msg"
|
|
116
|
+
|
|
117
|
+
if [ ! -f "$hook_path" ]; then
|
|
118
|
+
echo "Error: commit-msg hook not found"
|
|
119
|
+
return 1
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
"$hook_path" --help
|
|
123
|
+
}
|
|
79
124
|
```
|
|
80
125
|
|
|
81
126
|
#### Validating the package
|
|
@@ -83,7 +128,7 @@ python -m pip install -e .
|
|
|
83
128
|
After installing the package from GitLab, you may wish to run the test
|
|
84
129
|
suite to confirm everything is working as expected:
|
|
85
130
|
|
|
86
|
-
```
|
|
131
|
+
```bash
|
|
87
132
|
# From the root of the repository
|
|
88
133
|
pytest tests
|
|
89
134
|
```
|
|
@@ -94,3 +139,4 @@ Please have a look at the examples in
|
|
|
94
139
|
[resources](https://gitlab.com/SchmidtAF/plot-misc/-/tree/master/resources/examples)
|
|
95
140
|
for some possible recipes.
|
|
96
141
|
|
|
142
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '2.2.1'
|
|
@@ -30,11 +30,12 @@ from plot_misc.errors import (
|
|
|
30
30
|
is_df,
|
|
31
31
|
Error_MSG,
|
|
32
32
|
)
|
|
33
|
-
from typing import Any
|
|
33
|
+
from typing import Any
|
|
34
34
|
from plot_misc.constants import Real
|
|
35
35
|
|
|
36
36
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
37
37
|
def bar(data:pd.DataFrame, label:str, column:str,
|
|
38
|
+
positions:np.ndarray | list[Real] | None = None,
|
|
38
39
|
error_max:str | None = None, error_min:str | None = None,
|
|
39
40
|
colours:list[str]=['tab:blue', 'tab:pink'], transparency:float=0.7,
|
|
40
41
|
wd:Real=1.0, edgecolour:str='black',
|
|
@@ -54,9 +55,13 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
54
55
|
The column name for the axes labels.
|
|
55
56
|
column : `str`
|
|
56
57
|
The column name for the bar height values.
|
|
57
|
-
|
|
58
|
+
positions : `np.ndarray` or `list` or `None`, default `None`
|
|
59
|
+
Numeric positions for the bars along the category axis. If None,
|
|
60
|
+
bars are placed at integer positions 0, 1, 2, ... with tick
|
|
61
|
+
labels taken from the `label` column.
|
|
62
|
+
error_max : `str`, default `None`
|
|
58
63
|
column name for the upper value of the error line segment.
|
|
59
|
-
error_min : `str`, default `
|
|
64
|
+
error_min : `str`, default `None`
|
|
60
65
|
column name for the lower value of the error line segment.
|
|
61
66
|
colours : `list` [`str`], default ['tab:blue', 'tab:pink']
|
|
62
67
|
Colours for the bars; recycled if shorter than the number of bars.
|
|
@@ -68,7 +73,7 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
68
73
|
The bar edgecolour.
|
|
69
74
|
horizontal : `bool`, default `False`
|
|
70
75
|
Whether plot a horizontal bar chart.
|
|
71
|
-
ax : `plt.ax`, default `
|
|
76
|
+
ax : `plt.ax`, default `None`
|
|
72
77
|
The pyplot.axes object.
|
|
73
78
|
figsize : `tuple` [`float`, `float`], default (2, 2),
|
|
74
79
|
The figure size in inches, when ax is set to None.
|
|
@@ -96,6 +101,7 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
96
101
|
is_df(data)
|
|
97
102
|
is_type(label, str)
|
|
98
103
|
is_type(column, str)
|
|
104
|
+
is_type(positions, (type(None), np.ndarray, list))
|
|
99
105
|
is_type(colours, list)
|
|
100
106
|
is_type(transparency, float)
|
|
101
107
|
is_type(wd, (float, int))
|
|
@@ -117,10 +123,19 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
117
123
|
# ### check input
|
|
118
124
|
if any(data.isna().any()):
|
|
119
125
|
raise ValueError(Error_MSG.MISSING_DF.format('data'))
|
|
120
|
-
# ### get labels
|
|
126
|
+
# ### get labels and positions
|
|
121
127
|
labels = data[label]
|
|
128
|
+
if positions is None:
|
|
129
|
+
pos = np.arange(len(labels))
|
|
130
|
+
else:
|
|
131
|
+
pos = np.asarray(positions)
|
|
132
|
+
if len(pos) != len(labels):
|
|
133
|
+
raise ValueError(
|
|
134
|
+
f'Length of positions ({len(pos)}) does not match '
|
|
135
|
+
f'number of rows in data ({len(labels)}).'
|
|
136
|
+
)
|
|
122
137
|
# ### plotting
|
|
123
|
-
if horizontal
|
|
138
|
+
if not horizontal:
|
|
124
139
|
# plotting vertical bar chart
|
|
125
140
|
new_kwargs = _update_kwargs(update_dict=kwargs_bar,
|
|
126
141
|
edgecolor=edgecolour,
|
|
@@ -128,8 +143,10 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
128
143
|
alpha=transparency,
|
|
129
144
|
zorder=2,
|
|
130
145
|
)
|
|
131
|
-
bars = ax.bar(
|
|
146
|
+
bars = ax.bar(pos, height=data[column], **new_kwargs,
|
|
132
147
|
)
|
|
148
|
+
ax.set_xticks(pos)
|
|
149
|
+
ax.set_xticklabels(labels)
|
|
133
150
|
else:
|
|
134
151
|
# plotting horizontal bar chart
|
|
135
152
|
new_kwargs = _update_kwargs(update_dict=kwargs_bar,
|
|
@@ -138,13 +155,15 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
138
155
|
alpha=transparency,
|
|
139
156
|
zorder=2,
|
|
140
157
|
)
|
|
141
|
-
bars = ax.barh(
|
|
158
|
+
bars = ax.barh(pos, width=data[column], **new_kwargs,
|
|
142
159
|
)
|
|
160
|
+
ax.set_yticks(pos)
|
|
161
|
+
ax.set_yticklabels(labels)
|
|
143
162
|
# do we need to plot error bars
|
|
144
163
|
if error_min is not None or error_max is not None:
|
|
145
164
|
# finding the mid points of the bars and
|
|
146
165
|
# initialising the bounds, allowing for one-sided limits.
|
|
147
|
-
if horizontal
|
|
166
|
+
if not horizontal:
|
|
148
167
|
min_l = [b.get_y() + b.get_height() for b in bars]
|
|
149
168
|
max_l = min_l.copy()
|
|
150
169
|
else:
|
|
@@ -164,7 +183,7 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
164
183
|
color='black',
|
|
165
184
|
zorder=1,
|
|
166
185
|
)
|
|
167
|
-
if horizontal
|
|
186
|
+
if not horizontal:
|
|
168
187
|
mids = [b.get_x() + b.get_width() / 2 for b in bars]
|
|
169
188
|
ax.vlines(mids, min_l, max_l, **new_kwargs_error,)
|
|
170
189
|
else:
|
|
@@ -178,10 +197,11 @@ def bar(data:pd.DataFrame, label:str, column:str,
|
|
|
178
197
|
|
|
179
198
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
180
199
|
def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
200
|
+
positions:np.ndarray | list[Real] | None = None,
|
|
181
201
|
colours:list[str]=['tab:blue', 'tab:pink'],
|
|
182
202
|
transparency:float=0.7, wd:Real=1.0, edgecolour:str='black',
|
|
183
203
|
horizontal:bool = False, figsize:tuple[Real,Real] = (2,2),
|
|
184
|
-
ax:plt.Axes | None = None, **kwargs:
|
|
204
|
+
ax:plt.Axes | None = None, **kwargs:Any,
|
|
185
205
|
) -> tuple[plt.Figure, plt.Axes]:
|
|
186
206
|
"""
|
|
187
207
|
Plot a stacked bar chart with each bar divided into segments.
|
|
@@ -194,6 +214,9 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
194
214
|
Column name used for bar labels.
|
|
195
215
|
columns : `list` [`str`]
|
|
196
216
|
Column names representing bar segments to stack.
|
|
217
|
+
positions : `np.ndarray` or `list` or `None`, default `None`
|
|
218
|
+
Numeric positions for the bars along the category axis. If None,
|
|
219
|
+
bars are placed at integer positions 0, 1, 2, ...
|
|
197
220
|
colours : `list` [`str`]
|
|
198
221
|
List of colours for each stack segment.
|
|
199
222
|
transparency : `float`, default 0.7
|
|
@@ -204,7 +227,7 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
204
227
|
Colour for bar borders.
|
|
205
228
|
horizontal : `bool`, default `False`
|
|
206
229
|
Whether plot a horizontal barchart.
|
|
207
|
-
ax : `plt.ax`, default `
|
|
230
|
+
ax : `plt.ax`, default `None`
|
|
208
231
|
The pyplot.axes object.
|
|
209
232
|
figsize : `tuple` [`float`, `float`], default (2, 2),
|
|
210
233
|
The figure size in inches, when ax is set to None.
|
|
@@ -222,6 +245,7 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
222
245
|
is_df(data)
|
|
223
246
|
is_type(label, str)
|
|
224
247
|
is_type(columns, list)
|
|
248
|
+
is_type(positions, (type(None), np.ndarray, list))
|
|
225
249
|
is_type(colours, list)
|
|
226
250
|
is_type(transparency, float)
|
|
227
251
|
is_type(wd, (float, int))
|
|
@@ -233,7 +257,7 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
233
257
|
f, ax = plt.subplots(figsize=figsize)
|
|
234
258
|
else:
|
|
235
259
|
f = ax.figure
|
|
236
|
-
# ### should not be any
|
|
260
|
+
# ### should not be any missing
|
|
237
261
|
# NOTE consider making this into a function
|
|
238
262
|
if any(data.isna().any()):
|
|
239
263
|
raise ValueError(Error_MSG.MISSING_DF.format('data'))
|
|
@@ -254,17 +278,17 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
254
278
|
color=colours[idx],
|
|
255
279
|
alpha=transparency,
|
|
256
280
|
)
|
|
257
|
-
if horizontal
|
|
281
|
+
if not horizontal:
|
|
258
282
|
new_kwargs = _update_kwargs(new_kwargs, bottom=left,
|
|
259
283
|
)
|
|
260
284
|
else:
|
|
261
285
|
new_kwargs = _update_kwargs(new_kwargs, left=left,
|
|
262
286
|
)
|
|
263
287
|
# The actual plotting
|
|
264
|
-
# NOTE adding wd here because
|
|
288
|
+
# NOTE adding wd here because bar assigns it to either width or
|
|
265
289
|
# height depending on horizontal.
|
|
266
|
-
_, ax = bar(data=data, label=label, column=name,
|
|
267
|
-
wd=wd, ax=ax, kwargs_bar=new_kwargs,
|
|
290
|
+
_, ax = bar(data=data, label=label, column=name, positions=positions,
|
|
291
|
+
horizontal=horizontal, wd=wd, ax=ax, kwargs_bar=new_kwargs,
|
|
268
292
|
)
|
|
269
293
|
# updating the coordinate where the last bar stops
|
|
270
294
|
left = left + data[name]
|
|
@@ -277,6 +301,7 @@ def stack_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
277
301
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
278
302
|
def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
279
303
|
subtotal_col: str | None = None,
|
|
304
|
+
positions:np.ndarray | list[Real] | None = None,
|
|
280
305
|
colours:tuple[str,str]=('grey','tab:blue'),
|
|
281
306
|
transparency:tuple[float,float]=(0.7,0.9),
|
|
282
307
|
wd:tuple[float,float]=(1,0.6),
|
|
@@ -299,8 +324,11 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
299
324
|
Column name for axis labels.
|
|
300
325
|
total_col : `str`
|
|
301
326
|
Column containing values for the base (total) bars.
|
|
302
|
-
subtotal_col : `str` or `None`, default `
|
|
327
|
+
subtotal_col : `str` or `None`, default `None`
|
|
303
328
|
Column containing values for (smaller) overlaid subtotal bars.
|
|
329
|
+
positions : `np.ndarray` or `list` or `None`, default `None`
|
|
330
|
+
Numeric positions for the bars along the category axis. If None,
|
|
331
|
+
bars are placed at integer positions 0, 1, 2, ...
|
|
304
332
|
colours : `tuple` [`str`,`str`], default ("grey", "tab:blue")
|
|
305
333
|
Colours for the total and subtotal bars.
|
|
306
334
|
transparency : `tuple` [`float`,`float`], default (0.7, 0.9)
|
|
@@ -339,6 +367,7 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
339
367
|
is_type(ax, (type(None), plt.Axes))
|
|
340
368
|
is_type(total_col, str)
|
|
341
369
|
is_type(subtotal_col, (str, type(None)))
|
|
370
|
+
is_type(positions, (type(None), np.ndarray, list))
|
|
342
371
|
is_type(zorder, tuple)
|
|
343
372
|
is_type(colours, tuple)
|
|
344
373
|
is_type(transparency, tuple)
|
|
@@ -370,6 +399,7 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
370
399
|
ax=ax,
|
|
371
400
|
label=label,
|
|
372
401
|
column=total_col,
|
|
402
|
+
positions=positions,
|
|
373
403
|
colours=[colours[0]],
|
|
374
404
|
transparency=transparency[0],
|
|
375
405
|
wd=wd[0],
|
|
@@ -378,7 +408,7 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
378
408
|
kwargs_bar=new_total_kwargs_bar,
|
|
379
409
|
)
|
|
380
410
|
# plot subtotal
|
|
381
|
-
if
|
|
411
|
+
if subtotal_col is not None:
|
|
382
412
|
subtotal = data[subtotal_col]
|
|
383
413
|
# updating kwargs
|
|
384
414
|
new_subtotal_kwargs_bar = _update_kwargs(
|
|
@@ -390,6 +420,7 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
390
420
|
ax=ax,
|
|
391
421
|
label=label,
|
|
392
422
|
column=subtotal_col,
|
|
423
|
+
positions=positions,
|
|
393
424
|
colours=[colours[1]],
|
|
394
425
|
transparency=transparency[1],
|
|
395
426
|
wd=wd[1],
|
|
@@ -405,6 +436,7 @@ def subtotal_bar(data:pd.DataFrame, label:str, total_col:str,
|
|
|
405
436
|
|
|
406
437
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
407
438
|
def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
439
|
+
group_positions:np.ndarray | list[Real] | None = None,
|
|
408
440
|
errors_max:list[str] | None = None,
|
|
409
441
|
errors_min:list[str] | None = None,
|
|
410
442
|
colours:list[str]=['tab:blue', 'tab:pink'],
|
|
@@ -433,10 +465,14 @@ def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
433
465
|
Column name for group labels.
|
|
434
466
|
column : `list` [`str`]
|
|
435
467
|
Value columns to plot as grouped bars.
|
|
436
|
-
|
|
468
|
+
group_positions : `np.ndarray` or `list` or `None`, default `None`
|
|
469
|
+
Numeric positions for the group centres along the category axis.
|
|
470
|
+
If None, groups are placed at positions determined by
|
|
471
|
+
`group_spacing` (0, group_spacing, 2*group_spacing, ...).
|
|
472
|
+
errors_max : `list` [`str`] or `None`, default `None`
|
|
437
473
|
Column names in `data` containing the upper values of the error bars.
|
|
438
474
|
Should be structured similarly to `columns` if used.
|
|
439
|
-
errors_min : `list` [`str`] or `None` default `
|
|
475
|
+
errors_min : `list` [`str`] or `None` default `None`
|
|
440
476
|
Column names in `data` containing the lower values of the error bars.
|
|
441
477
|
colours : `list` [`str`], default ['tab:blue', 'tab:pink']
|
|
442
478
|
Colours for the bars. Recycled if fewer colours than `columns`.
|
|
@@ -448,7 +484,7 @@ def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
448
484
|
The bar edge colours.
|
|
449
485
|
horizontal : `bool`, default `False`
|
|
450
486
|
Whether plot a horizontal barchart.
|
|
451
|
-
ax : `plt.ax`, default `
|
|
487
|
+
ax : `plt.ax`, default `None`
|
|
452
488
|
The pyplot.axes object.
|
|
453
489
|
figsize : `tuple` [`float`, `float`], default (2, 2),
|
|
454
490
|
The figure size in inches, when ax is set to None.
|
|
@@ -464,11 +500,10 @@ def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
464
500
|
ax : plt.Axes
|
|
465
501
|
The matplotlib Axes object with the plot.
|
|
466
502
|
"""
|
|
467
|
-
# constants
|
|
468
|
-
OFFSET_COL = "__offset__"
|
|
469
503
|
# check input - most will be done by bar, just keeping the minimum
|
|
470
504
|
is_df(data)
|
|
471
505
|
is_type(columns, list)
|
|
506
|
+
is_type(group_positions, (type(None), np.ndarray, list))
|
|
472
507
|
is_type(errors_max, (type(None),list))
|
|
473
508
|
is_type(errors_min, (type(None),list))
|
|
474
509
|
is_type(horizontal, bool)
|
|
@@ -483,8 +518,16 @@ def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
483
518
|
# ### prepare the loop
|
|
484
519
|
# the number of bars for each group
|
|
485
520
|
n_bars = len(columns)
|
|
486
|
-
# the
|
|
487
|
-
|
|
521
|
+
# the base position of each group
|
|
522
|
+
if group_positions is None:
|
|
523
|
+
base = np.arange(data.shape[0]) * group_spacing
|
|
524
|
+
else:
|
|
525
|
+
base = np.asarray(group_positions)
|
|
526
|
+
if len(base) != data.shape[0]:
|
|
527
|
+
raise ValueError(
|
|
528
|
+
f'Length of group_positions ({len(base)}) does not '
|
|
529
|
+
f'match number of rows in data ({data.shape[0]}).'
|
|
530
|
+
)
|
|
488
531
|
# the total width of all the bars in a single group
|
|
489
532
|
spacing_per_bar = bar_spacing * wd
|
|
490
533
|
total_spacing = spacing_per_bar * (n_bars - 1)
|
|
@@ -494,20 +537,19 @@ def group_bar(data:pd.DataFrame, label:str, columns:list[str],
|
|
|
494
537
|
group_width = wd * n_bars + total_spacing
|
|
495
538
|
tick_pos = base + (group_width - wd) / 2
|
|
496
539
|
# looping
|
|
497
|
-
df_offset = data.copy()
|
|
498
540
|
for i, column in enumerate(columns):
|
|
499
541
|
# the location of the bar
|
|
500
542
|
offset = base + i * (wd + spacing_per_bar)
|
|
501
|
-
df_offset[OFFSET_COL] = offset
|
|
502
543
|
# cycling the colours
|
|
503
544
|
col = colours[i % len(colours)]
|
|
504
545
|
# the limits
|
|
505
546
|
err_max = errors_max[i] if errors_max else None
|
|
506
547
|
err_min = errors_min[i] if errors_min else None
|
|
507
548
|
_ = bar(
|
|
508
|
-
data=
|
|
509
|
-
label=
|
|
549
|
+
data=data,
|
|
550
|
+
label=label,
|
|
510
551
|
column=column,
|
|
552
|
+
positions=offset,
|
|
511
553
|
error_max=err_max,
|
|
512
554
|
error_min=err_min,
|
|
513
555
|
colours=[col],
|
|
@@ -42,9 +42,9 @@ class ForestNames(object):
|
|
|
42
42
|
PVALUE = 'p-value'
|
|
43
43
|
CI = 'confidence_interval'
|
|
44
44
|
data_table = 'data_table'
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
EmpiricalSupport_Coverage = 'coverage'
|
|
46
|
+
EmpiricalSupport_Compatibility = 'compatibility'
|
|
47
|
+
EmpiricalSupportResults = 'results_'
|
|
48
48
|
|
|
49
49
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
50
50
|
# Utils Names
|
|
@@ -103,7 +103,7 @@ class NamesIncidenceMatrix(object):
|
|
|
103
103
|
GRID_POS_O = 'outline'
|
|
104
104
|
|
|
105
105
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
106
|
-
class
|
|
106
|
+
class NamesMachineLearning(object):
|
|
107
107
|
'''
|
|
108
108
|
Names used by machinelearning.py
|
|
109
109
|
'''
|