py-geodetector 0.1.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.
- py_geodetector-0.1.1/.gitignore +4 -0
- py_geodetector-0.1.1/PKG-INFO +63 -0
- py_geodetector-0.1.1/README.md +50 -0
- py_geodetector-0.1.1/example.ipynb +437 -0
- py_geodetector-0.1.1/pyproject.toml +29 -0
- py_geodetector-0.1.1/src/__init__.py +0 -0
- py_geodetector-0.1.1/src/py_geodetector/__init__.py +1 -0
- py_geodetector-0.1.1/src/py_geodetector/example_data/disease.csv +186 -0
- py_geodetector-0.1.1/src/py_geodetector/geodetector.py +191 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: py_geodetector
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: A simple Python package for the geodetector
|
|
5
|
+
Project-URL: Homepage, https://github.com/djw-easy/GeoDetector
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/djw-easy/GeoDetector/issues
|
|
7
|
+
Author-email: djw <djweasy@163.com>
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# A simple Python package for the geodetector
|
|
15
|
+
|
|
16
|
+
# Install
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
pip install py-geodetector
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
# Usage
|
|
23
|
+
|
|
24
|
+
A quick example of geodetector usage is given in the ./example.ipynb.
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from py_geodetector import load_example_data, GeoDetector
|
|
28
|
+
|
|
29
|
+
# load example data
|
|
30
|
+
df = load_example_data()
|
|
31
|
+
|
|
32
|
+
gd = GeoDetector(df)
|
|
33
|
+
# factor detect
|
|
34
|
+
factor_df = gd.factor_dector()
|
|
35
|
+
|
|
36
|
+
# interaction detect
|
|
37
|
+
interaction_df = gd.interaction_detector()
|
|
38
|
+
# or you can generate the interaction relationship as the same time
|
|
39
|
+
interaction_df, interaction_relationship_df = gd.interaction_detector(relationship=True)
|
|
40
|
+
|
|
41
|
+
# ecological detect
|
|
42
|
+
ecological_df = gd.ecological_detector()
|
|
43
|
+
|
|
44
|
+
# plot
|
|
45
|
+
# use a heatmap visualize the interaction detect result,
|
|
46
|
+
# red text means that the ecological detection results show a significant difference
|
|
47
|
+
gd.plot(value_fontsize=14, tick_fontsize=16, colorbar_fontsize=14);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
# Reference
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
@article{wang2010geographical,
|
|
54
|
+
title={Geographical detectors-based health risk assessment and its application in the neural tube defects study of the Heshun Region, China},
|
|
55
|
+
author={Wang, Jin-Feng and Li, Xin-Hu and Christakos, George and Liao, Yi-Lan and Zhang, Tin and Gu, Xue and Zheng, Xiao-Ying},
|
|
56
|
+
journal={International Journal of Geographical Information Science},
|
|
57
|
+
volume={24},
|
|
58
|
+
number={1},
|
|
59
|
+
pages={107-127},
|
|
60
|
+
year={2010},
|
|
61
|
+
publisher={Taylor \& Francis}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# A simple Python package for the geodetector
|
|
2
|
+
|
|
3
|
+
# Install
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
pip install py-geodetector
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
# Usage
|
|
10
|
+
|
|
11
|
+
A quick example of geodetector usage is given in the ./example.ipynb.
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from py_geodetector import load_example_data, GeoDetector
|
|
15
|
+
|
|
16
|
+
# load example data
|
|
17
|
+
df = load_example_data()
|
|
18
|
+
|
|
19
|
+
gd = GeoDetector(df)
|
|
20
|
+
# factor detect
|
|
21
|
+
factor_df = gd.factor_dector()
|
|
22
|
+
|
|
23
|
+
# interaction detect
|
|
24
|
+
interaction_df = gd.interaction_detector()
|
|
25
|
+
# or you can generate the interaction relationship as the same time
|
|
26
|
+
interaction_df, interaction_relationship_df = gd.interaction_detector(relationship=True)
|
|
27
|
+
|
|
28
|
+
# ecological detect
|
|
29
|
+
ecological_df = gd.ecological_detector()
|
|
30
|
+
|
|
31
|
+
# plot
|
|
32
|
+
# use a heatmap visualize the interaction detect result,
|
|
33
|
+
# red text means that the ecological detection results show a significant difference
|
|
34
|
+
gd.plot(value_fontsize=14, tick_fontsize=16, colorbar_fontsize=14);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
# Reference
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
@article{wang2010geographical,
|
|
41
|
+
title={Geographical detectors-based health risk assessment and its application in the neural tube defects study of the Heshun Region, China},
|
|
42
|
+
author={Wang, Jin-Feng and Li, Xin-Hu and Christakos, George and Liao, Yi-Lan and Zhang, Tin and Gu, Xue and Zheng, Xiao-Ying},
|
|
43
|
+
journal={International Journal of Geographical Information Science},
|
|
44
|
+
volume={24},
|
|
45
|
+
number={1},
|
|
46
|
+
pages={107-127},
|
|
47
|
+
year={2010},
|
|
48
|
+
publisher={Taylor \& Francis}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "code",
|
|
5
|
+
"execution_count": 1,
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"outputs": [],
|
|
8
|
+
"source": [
|
|
9
|
+
"from py_geodetector import load_example_data, GeoDetector"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"cell_type": "code",
|
|
14
|
+
"execution_count": 2,
|
|
15
|
+
"metadata": {},
|
|
16
|
+
"outputs": [
|
|
17
|
+
{
|
|
18
|
+
"data": {
|
|
19
|
+
"text/html": [
|
|
20
|
+
"<div>\n",
|
|
21
|
+
"<style scoped>\n",
|
|
22
|
+
" .dataframe tbody tr th:only-of-type {\n",
|
|
23
|
+
" vertical-align: middle;\n",
|
|
24
|
+
" }\n",
|
|
25
|
+
"\n",
|
|
26
|
+
" .dataframe tbody tr th {\n",
|
|
27
|
+
" vertical-align: top;\n",
|
|
28
|
+
" }\n",
|
|
29
|
+
"\n",
|
|
30
|
+
" .dataframe thead th {\n",
|
|
31
|
+
" text-align: right;\n",
|
|
32
|
+
" }\n",
|
|
33
|
+
"</style>\n",
|
|
34
|
+
"<table border=\"1\" class=\"dataframe\">\n",
|
|
35
|
+
" <thead>\n",
|
|
36
|
+
" <tr style=\"text-align: right;\">\n",
|
|
37
|
+
" <th></th>\n",
|
|
38
|
+
" <th>incidence</th>\n",
|
|
39
|
+
" <th>type</th>\n",
|
|
40
|
+
" <th>region</th>\n",
|
|
41
|
+
" <th>level</th>\n",
|
|
42
|
+
" </tr>\n",
|
|
43
|
+
" </thead>\n",
|
|
44
|
+
" <tbody>\n",
|
|
45
|
+
" <tr>\n",
|
|
46
|
+
" <th>0</th>\n",
|
|
47
|
+
" <td>5.94</td>\n",
|
|
48
|
+
" <td>7</td>\n",
|
|
49
|
+
" <td>5</td>\n",
|
|
50
|
+
" <td>5</td>\n",
|
|
51
|
+
" </tr>\n",
|
|
52
|
+
" <tr>\n",
|
|
53
|
+
" <th>1</th>\n",
|
|
54
|
+
" <td>5.87</td>\n",
|
|
55
|
+
" <td>5</td>\n",
|
|
56
|
+
" <td>5</td>\n",
|
|
57
|
+
" <td>5</td>\n",
|
|
58
|
+
" </tr>\n",
|
|
59
|
+
" <tr>\n",
|
|
60
|
+
" <th>2</th>\n",
|
|
61
|
+
" <td>5.92</td>\n",
|
|
62
|
+
" <td>5</td>\n",
|
|
63
|
+
" <td>5</td>\n",
|
|
64
|
+
" <td>5</td>\n",
|
|
65
|
+
" </tr>\n",
|
|
66
|
+
" <tr>\n",
|
|
67
|
+
" <th>3</th>\n",
|
|
68
|
+
" <td>6.32</td>\n",
|
|
69
|
+
" <td>1</td>\n",
|
|
70
|
+
" <td>7</td>\n",
|
|
71
|
+
" <td>1</td>\n",
|
|
72
|
+
" </tr>\n",
|
|
73
|
+
" <tr>\n",
|
|
74
|
+
" <th>4</th>\n",
|
|
75
|
+
" <td>6.49</td>\n",
|
|
76
|
+
" <td>3</td>\n",
|
|
77
|
+
" <td>2</td>\n",
|
|
78
|
+
" <td>4</td>\n",
|
|
79
|
+
" </tr>\n",
|
|
80
|
+
" </tbody>\n",
|
|
81
|
+
"</table>\n",
|
|
82
|
+
"</div>"
|
|
83
|
+
],
|
|
84
|
+
"text/plain": [
|
|
85
|
+
" incidence type region level\n",
|
|
86
|
+
"0 5.94 7 5 5\n",
|
|
87
|
+
"1 5.87 5 5 5\n",
|
|
88
|
+
"2 5.92 5 5 5\n",
|
|
89
|
+
"3 6.32 1 7 1\n",
|
|
90
|
+
"4 6.49 3 2 4"
|
|
91
|
+
]
|
|
92
|
+
},
|
|
93
|
+
"execution_count": 2,
|
|
94
|
+
"metadata": {},
|
|
95
|
+
"output_type": "execute_result"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"source": [
|
|
99
|
+
"df = load_example_data()\n",
|
|
100
|
+
"df.head()"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"cell_type": "code",
|
|
105
|
+
"execution_count": 3,
|
|
106
|
+
"metadata": {},
|
|
107
|
+
"outputs": [],
|
|
108
|
+
"source": [
|
|
109
|
+
"gd = GeoDetector(df, 'incidence', ['type', 'region', 'level'])"
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"cell_type": "code",
|
|
114
|
+
"execution_count": 4,
|
|
115
|
+
"metadata": {},
|
|
116
|
+
"outputs": [
|
|
117
|
+
{
|
|
118
|
+
"data": {
|
|
119
|
+
"text/html": [
|
|
120
|
+
"<div>\n",
|
|
121
|
+
"<style scoped>\n",
|
|
122
|
+
" .dataframe tbody tr th:only-of-type {\n",
|
|
123
|
+
" vertical-align: middle;\n",
|
|
124
|
+
" }\n",
|
|
125
|
+
"\n",
|
|
126
|
+
" .dataframe tbody tr th {\n",
|
|
127
|
+
" vertical-align: top;\n",
|
|
128
|
+
" }\n",
|
|
129
|
+
"\n",
|
|
130
|
+
" .dataframe thead th {\n",
|
|
131
|
+
" text-align: right;\n",
|
|
132
|
+
" }\n",
|
|
133
|
+
"</style>\n",
|
|
134
|
+
"<table border=\"1\" class=\"dataframe\">\n",
|
|
135
|
+
" <thead>\n",
|
|
136
|
+
" <tr style=\"text-align: right;\">\n",
|
|
137
|
+
" <th></th>\n",
|
|
138
|
+
" <th>type</th>\n",
|
|
139
|
+
" <th>region</th>\n",
|
|
140
|
+
" <th>level</th>\n",
|
|
141
|
+
" </tr>\n",
|
|
142
|
+
" </thead>\n",
|
|
143
|
+
" <tbody>\n",
|
|
144
|
+
" <tr>\n",
|
|
145
|
+
" <th>q statistic</th>\n",
|
|
146
|
+
" <td>0.385717</td>\n",
|
|
147
|
+
" <td>0.637774</td>\n",
|
|
148
|
+
" <td>0.606709</td>\n",
|
|
149
|
+
" </tr>\n",
|
|
150
|
+
" <tr>\n",
|
|
151
|
+
" <th>p value</th>\n",
|
|
152
|
+
" <td>0.363236</td>\n",
|
|
153
|
+
" <td>0.000117</td>\n",
|
|
154
|
+
" <td>0.040804</td>\n",
|
|
155
|
+
" </tr>\n",
|
|
156
|
+
" </tbody>\n",
|
|
157
|
+
"</table>\n",
|
|
158
|
+
"</div>"
|
|
159
|
+
],
|
|
160
|
+
"text/plain": [
|
|
161
|
+
" type region level\n",
|
|
162
|
+
"q statistic 0.385717 0.637774 0.606709\n",
|
|
163
|
+
"p value 0.363236 0.000117 0.040804"
|
|
164
|
+
]
|
|
165
|
+
},
|
|
166
|
+
"execution_count": 4,
|
|
167
|
+
"metadata": {},
|
|
168
|
+
"output_type": "execute_result"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"source": [
|
|
172
|
+
"gd.factor_dector()"
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"cell_type": "code",
|
|
177
|
+
"execution_count": 5,
|
|
178
|
+
"metadata": {},
|
|
179
|
+
"outputs": [
|
|
180
|
+
{
|
|
181
|
+
"data": {
|
|
182
|
+
"text/html": [
|
|
183
|
+
"<div>\n",
|
|
184
|
+
"<style scoped>\n",
|
|
185
|
+
" .dataframe tbody tr th:only-of-type {\n",
|
|
186
|
+
" vertical-align: middle;\n",
|
|
187
|
+
" }\n",
|
|
188
|
+
"\n",
|
|
189
|
+
" .dataframe tbody tr th {\n",
|
|
190
|
+
" vertical-align: top;\n",
|
|
191
|
+
" }\n",
|
|
192
|
+
"\n",
|
|
193
|
+
" .dataframe thead th {\n",
|
|
194
|
+
" text-align: right;\n",
|
|
195
|
+
" }\n",
|
|
196
|
+
"</style>\n",
|
|
197
|
+
"<table border=\"1\" class=\"dataframe\">\n",
|
|
198
|
+
" <thead>\n",
|
|
199
|
+
" <tr style=\"text-align: right;\">\n",
|
|
200
|
+
" <th></th>\n",
|
|
201
|
+
" <th>type</th>\n",
|
|
202
|
+
" <th>region</th>\n",
|
|
203
|
+
" <th>level</th>\n",
|
|
204
|
+
" </tr>\n",
|
|
205
|
+
" </thead>\n",
|
|
206
|
+
" <tbody>\n",
|
|
207
|
+
" <tr>\n",
|
|
208
|
+
" <th>type</th>\n",
|
|
209
|
+
" <td>0.385717</td>\n",
|
|
210
|
+
" <td>NaN</td>\n",
|
|
211
|
+
" <td>NaN</td>\n",
|
|
212
|
+
" </tr>\n",
|
|
213
|
+
" <tr>\n",
|
|
214
|
+
" <th>region</th>\n",
|
|
215
|
+
" <td>0.735681</td>\n",
|
|
216
|
+
" <td>0.637774</td>\n",
|
|
217
|
+
" <td>NaN</td>\n",
|
|
218
|
+
" </tr>\n",
|
|
219
|
+
" <tr>\n",
|
|
220
|
+
" <th>level</th>\n",
|
|
221
|
+
" <td>0.663524</td>\n",
|
|
222
|
+
" <td>0.713597</td>\n",
|
|
223
|
+
" <td>0.606709</td>\n",
|
|
224
|
+
" </tr>\n",
|
|
225
|
+
" </tbody>\n",
|
|
226
|
+
"</table>\n",
|
|
227
|
+
"</div>"
|
|
228
|
+
],
|
|
229
|
+
"text/plain": [
|
|
230
|
+
" type region level\n",
|
|
231
|
+
"type 0.385717 NaN NaN\n",
|
|
232
|
+
"region 0.735681 0.637774 NaN\n",
|
|
233
|
+
"level 0.663524 0.713597 0.606709"
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
"execution_count": 5,
|
|
237
|
+
"metadata": {},
|
|
238
|
+
"output_type": "execute_result"
|
|
239
|
+
}
|
|
240
|
+
],
|
|
241
|
+
"source": [
|
|
242
|
+
"gd.interaction_detector()"
|
|
243
|
+
]
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"cell_type": "code",
|
|
247
|
+
"execution_count": 6,
|
|
248
|
+
"metadata": {},
|
|
249
|
+
"outputs": [
|
|
250
|
+
{
|
|
251
|
+
"data": {
|
|
252
|
+
"text/html": [
|
|
253
|
+
"<div>\n",
|
|
254
|
+
"<style scoped>\n",
|
|
255
|
+
" .dataframe tbody tr th:only-of-type {\n",
|
|
256
|
+
" vertical-align: middle;\n",
|
|
257
|
+
" }\n",
|
|
258
|
+
"\n",
|
|
259
|
+
" .dataframe tbody tr th {\n",
|
|
260
|
+
" vertical-align: top;\n",
|
|
261
|
+
" }\n",
|
|
262
|
+
"\n",
|
|
263
|
+
" .dataframe thead th {\n",
|
|
264
|
+
" text-align: right;\n",
|
|
265
|
+
" }\n",
|
|
266
|
+
"</style>\n",
|
|
267
|
+
"<table border=\"1\" class=\"dataframe\">\n",
|
|
268
|
+
" <thead>\n",
|
|
269
|
+
" <tr style=\"text-align: right;\">\n",
|
|
270
|
+
" <th></th>\n",
|
|
271
|
+
" <th>type</th>\n",
|
|
272
|
+
" <th>region</th>\n",
|
|
273
|
+
" <th>level</th>\n",
|
|
274
|
+
" </tr>\n",
|
|
275
|
+
" </thead>\n",
|
|
276
|
+
" <tbody>\n",
|
|
277
|
+
" <tr>\n",
|
|
278
|
+
" <th>type</th>\n",
|
|
279
|
+
" <td>NaN</td>\n",
|
|
280
|
+
" <td>NaN</td>\n",
|
|
281
|
+
" <td>NaN</td>\n",
|
|
282
|
+
" </tr>\n",
|
|
283
|
+
" <tr>\n",
|
|
284
|
+
" <th>region</th>\n",
|
|
285
|
+
" <td>Enhance, bi-</td>\n",
|
|
286
|
+
" <td>NaN</td>\n",
|
|
287
|
+
" <td>NaN</td>\n",
|
|
288
|
+
" </tr>\n",
|
|
289
|
+
" <tr>\n",
|
|
290
|
+
" <th>level</th>\n",
|
|
291
|
+
" <td>Enhance, bi-</td>\n",
|
|
292
|
+
" <td>Enhance, bi-</td>\n",
|
|
293
|
+
" <td>NaN</td>\n",
|
|
294
|
+
" </tr>\n",
|
|
295
|
+
" </tbody>\n",
|
|
296
|
+
"</table>\n",
|
|
297
|
+
"</div>"
|
|
298
|
+
],
|
|
299
|
+
"text/plain": [
|
|
300
|
+
" type region level\n",
|
|
301
|
+
"type NaN NaN NaN\n",
|
|
302
|
+
"region Enhance, bi- NaN NaN\n",
|
|
303
|
+
"level Enhance, bi- Enhance, bi- NaN"
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
"execution_count": 6,
|
|
307
|
+
"metadata": {},
|
|
308
|
+
"output_type": "execute_result"
|
|
309
|
+
}
|
|
310
|
+
],
|
|
311
|
+
"source": [
|
|
312
|
+
"gd.interaction_detector(relationship=True)[1]"
|
|
313
|
+
]
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
"cell_type": "code",
|
|
317
|
+
"execution_count": 7,
|
|
318
|
+
"metadata": {},
|
|
319
|
+
"outputs": [
|
|
320
|
+
{
|
|
321
|
+
"data": {
|
|
322
|
+
"text/html": [
|
|
323
|
+
"<div>\n",
|
|
324
|
+
"<style scoped>\n",
|
|
325
|
+
" .dataframe tbody tr th:only-of-type {\n",
|
|
326
|
+
" vertical-align: middle;\n",
|
|
327
|
+
" }\n",
|
|
328
|
+
"\n",
|
|
329
|
+
" .dataframe tbody tr th {\n",
|
|
330
|
+
" vertical-align: top;\n",
|
|
331
|
+
" }\n",
|
|
332
|
+
"\n",
|
|
333
|
+
" .dataframe thead th {\n",
|
|
334
|
+
" text-align: right;\n",
|
|
335
|
+
" }\n",
|
|
336
|
+
"</style>\n",
|
|
337
|
+
"<table border=\"1\" class=\"dataframe\">\n",
|
|
338
|
+
" <thead>\n",
|
|
339
|
+
" <tr style=\"text-align: right;\">\n",
|
|
340
|
+
" <th></th>\n",
|
|
341
|
+
" <th>type</th>\n",
|
|
342
|
+
" <th>region</th>\n",
|
|
343
|
+
" <th>level</th>\n",
|
|
344
|
+
" </tr>\n",
|
|
345
|
+
" </thead>\n",
|
|
346
|
+
" <tbody>\n",
|
|
347
|
+
" <tr>\n",
|
|
348
|
+
" <th>type</th>\n",
|
|
349
|
+
" <td>NaN</td>\n",
|
|
350
|
+
" <td>NaN</td>\n",
|
|
351
|
+
" <td>NaN</td>\n",
|
|
352
|
+
" </tr>\n",
|
|
353
|
+
" <tr>\n",
|
|
354
|
+
" <th>region</th>\n",
|
|
355
|
+
" <td>Y</td>\n",
|
|
356
|
+
" <td>NaN</td>\n",
|
|
357
|
+
" <td>NaN</td>\n",
|
|
358
|
+
" </tr>\n",
|
|
359
|
+
" <tr>\n",
|
|
360
|
+
" <th>level</th>\n",
|
|
361
|
+
" <td>Y</td>\n",
|
|
362
|
+
" <td>N</td>\n",
|
|
363
|
+
" <td>NaN</td>\n",
|
|
364
|
+
" </tr>\n",
|
|
365
|
+
" </tbody>\n",
|
|
366
|
+
"</table>\n",
|
|
367
|
+
"</div>"
|
|
368
|
+
],
|
|
369
|
+
"text/plain": [
|
|
370
|
+
" type region level\n",
|
|
371
|
+
"type NaN NaN NaN\n",
|
|
372
|
+
"region Y NaN NaN\n",
|
|
373
|
+
"level Y N NaN"
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
"execution_count": 7,
|
|
377
|
+
"metadata": {},
|
|
378
|
+
"output_type": "execute_result"
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
"source": [
|
|
382
|
+
"gd.ecological_detector()"
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"cell_type": "code",
|
|
387
|
+
"execution_count": 8,
|
|
388
|
+
"metadata": {},
|
|
389
|
+
"outputs": [
|
|
390
|
+
{
|
|
391
|
+
"data": {
|
|
392
|
+
"image/png": "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",
|
|
393
|
+
"text/plain": [
|
|
394
|
+
"<Figure size 432x288 with 2 Axes>"
|
|
395
|
+
]
|
|
396
|
+
},
|
|
397
|
+
"metadata": {
|
|
398
|
+
"needs_background": "light"
|
|
399
|
+
},
|
|
400
|
+
"output_type": "display_data"
|
|
401
|
+
}
|
|
402
|
+
],
|
|
403
|
+
"source": [
|
|
404
|
+
"gd.plot(value_fontsize=14, tick_fontsize=16, colorbar_fontsize=14);"
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"cell_type": "code",
|
|
409
|
+
"execution_count": null,
|
|
410
|
+
"metadata": {},
|
|
411
|
+
"outputs": [],
|
|
412
|
+
"source": []
|
|
413
|
+
}
|
|
414
|
+
],
|
|
415
|
+
"metadata": {
|
|
416
|
+
"kernelspec": {
|
|
417
|
+
"display_name": "geo",
|
|
418
|
+
"language": "python",
|
|
419
|
+
"name": "python3"
|
|
420
|
+
},
|
|
421
|
+
"language_info": {
|
|
422
|
+
"codemirror_mode": {
|
|
423
|
+
"name": "ipython",
|
|
424
|
+
"version": 3
|
|
425
|
+
},
|
|
426
|
+
"file_extension": ".py",
|
|
427
|
+
"mimetype": "text/x-python",
|
|
428
|
+
"name": "python",
|
|
429
|
+
"nbconvert_exporter": "python",
|
|
430
|
+
"pygments_lexer": "ipython3",
|
|
431
|
+
"version": "3.10.12"
|
|
432
|
+
},
|
|
433
|
+
"orig_nbformat": 4
|
|
434
|
+
},
|
|
435
|
+
"nbformat": 4,
|
|
436
|
+
"nbformat_minor": 2
|
|
437
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"numpy",
|
|
4
|
+
"pandas",
|
|
5
|
+
"scipy",
|
|
6
|
+
"hatchling",
|
|
7
|
+
"matplotlib"
|
|
8
|
+
]
|
|
9
|
+
build-backend = "hatchling.build"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
[project]
|
|
13
|
+
name = "py_geodetector"
|
|
14
|
+
version = "0.1.1"
|
|
15
|
+
authors = [
|
|
16
|
+
{ name = "djw", email = "djweasy@163.com" },
|
|
17
|
+
]
|
|
18
|
+
description = "A simple Python package for the geodetector"
|
|
19
|
+
readme = "README.md"
|
|
20
|
+
requires-python = ">=3.7"
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
"Homepage" = "https://github.com/djw-easy/GeoDetector"
|
|
29
|
+
"Bug Tracker" = "https://github.com/djw-easy/GeoDetector/issues"
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .geodetector import GeoDetector, load_example_data
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
incidence,type,region,level
|
|
2
|
+
5.94,7,5,5
|
|
3
|
+
5.87,5,5,5
|
|
4
|
+
5.92,5,5,5
|
|
5
|
+
6.32,1,7,1
|
|
6
|
+
6.49,3,2,4
|
|
7
|
+
6.46,3,2,4
|
|
8
|
+
6.51,3,2,4
|
|
9
|
+
6.7,3,2,4
|
|
10
|
+
6.68,3,2,4
|
|
11
|
+
6.65,3,2,4
|
|
12
|
+
6.65,3,2,4
|
|
13
|
+
6.6,3,2,4
|
|
14
|
+
6.66,3,2,4
|
|
15
|
+
5.86,5,5,5
|
|
16
|
+
6.93,3,2,4
|
|
17
|
+
6.5,3,2,4
|
|
18
|
+
6.37,3,2,4
|
|
19
|
+
6.64,3,2,4
|
|
20
|
+
6.43,7,9,1
|
|
21
|
+
7.01,2,9,1
|
|
22
|
+
6.77,2,9,1
|
|
23
|
+
6.36,7,9,1
|
|
24
|
+
6.44,7,9,3
|
|
25
|
+
6.52,7,9,1
|
|
26
|
+
5.83,5,6,7
|
|
27
|
+
6.32,7,9,1
|
|
28
|
+
6.33,7,9,1
|
|
29
|
+
6.46,7,9,1
|
|
30
|
+
6.63,7,9,6
|
|
31
|
+
6.53,3,9,1
|
|
32
|
+
6.59,7,9,4
|
|
33
|
+
6.58,2,9,1
|
|
34
|
+
6.63,3,9,6
|
|
35
|
+
6.61,2,9,1
|
|
36
|
+
7.04,3,9,4
|
|
37
|
+
5.89,5,6,5
|
|
38
|
+
6.57,2,9,1
|
|
39
|
+
6.53,3,9,4
|
|
40
|
+
6.58,3,9,4
|
|
41
|
+
6.53,3,9,1
|
|
42
|
+
6.55,3,9,4
|
|
43
|
+
6.57,2,9,1
|
|
44
|
+
6.57,1,7,1
|
|
45
|
+
6.49,2,7,4
|
|
46
|
+
6.56,2,9,4
|
|
47
|
+
6.57,1,7,1
|
|
48
|
+
5.97,5,6,5
|
|
49
|
+
6.54,2,7,4
|
|
50
|
+
6.71,3,9,6
|
|
51
|
+
6.58,3,9,1
|
|
52
|
+
6.63,7,9,6
|
|
53
|
+
7.42,3,2,6
|
|
54
|
+
6.71,3,4,1
|
|
55
|
+
6.82,3,2,6
|
|
56
|
+
6.56,3,2,6
|
|
57
|
+
6.82,3,2,6
|
|
58
|
+
5.86,5,6,7
|
|
59
|
+
6.8,3,2,6
|
|
60
|
+
7.74,3,2,6
|
|
61
|
+
6.92,3,2,6
|
|
62
|
+
6.75,3,2,6
|
|
63
|
+
7.06,3,2,6
|
|
64
|
+
7.1,3,2,6
|
|
65
|
+
6.69,3,4,6
|
|
66
|
+
6.81,3,2,6
|
|
67
|
+
6.99,3,2,6
|
|
68
|
+
6.79,3,2,6
|
|
69
|
+
5.98,5,6,5
|
|
70
|
+
7.01,3,2,6
|
|
71
|
+
7.2,3,2,6
|
|
72
|
+
6.95,3,2,4
|
|
73
|
+
6.74,3,4,6
|
|
74
|
+
6.77,3,4,1
|
|
75
|
+
6.73,3,4,6
|
|
76
|
+
6.57,7,3,3
|
|
77
|
+
7.55,7,3,3
|
|
78
|
+
6.04,1,6,5
|
|
79
|
+
6.28,7,3,3
|
|
80
|
+
6.38,7,3,3
|
|
81
|
+
6.21,7,3,3
|
|
82
|
+
6.33,7,3,3
|
|
83
|
+
6.19,7,3,3
|
|
84
|
+
6.45,7,3,2
|
|
85
|
+
6.19,7,3,2
|
|
86
|
+
6.14,7,3,2
|
|
87
|
+
6.2,7,3,2
|
|
88
|
+
6.14,3,3,2
|
|
89
|
+
5.95,1,5,5
|
|
90
|
+
6.27,7,3,3
|
|
91
|
+
6.14,3,3,2
|
|
92
|
+
6.18,7,1,2
|
|
93
|
+
6.09,7,1,2
|
|
94
|
+
6.04,7,1,3
|
|
95
|
+
6.01,7,5,2
|
|
96
|
+
6.01,7,5,3
|
|
97
|
+
6.09,7,1,3
|
|
98
|
+
5.85,5,6,5
|
|
99
|
+
5.88,7,5,5
|
|
100
|
+
5.8,5,6,7
|
|
101
|
+
5.78,5,6,7
|
|
102
|
+
5.7,5,6,7
|
|
103
|
+
5.82,5,6,7
|
|
104
|
+
5.73,5,6,7
|
|
105
|
+
5.79,5,6,7
|
|
106
|
+
5.8,5,6,7
|
|
107
|
+
6.45,1,8,3
|
|
108
|
+
6.47,1,8,3
|
|
109
|
+
6.11,3,8,1
|
|
110
|
+
5.98,7,5,5
|
|
111
|
+
6.12,1,8,3
|
|
112
|
+
6.15,1,8,1
|
|
113
|
+
6.04,3,8,1
|
|
114
|
+
6.06,3,8,3
|
|
115
|
+
5.95,3,8,1
|
|
116
|
+
6.09,3,8,1
|
|
117
|
+
6.11,3,8,1
|
|
118
|
+
6.27,1,8,1
|
|
119
|
+
6.28,1,8,1
|
|
120
|
+
6.28,1,8,1
|
|
121
|
+
5.96,1,5,5
|
|
122
|
+
6.23,1,8,1
|
|
123
|
+
6.53,1,8,1
|
|
124
|
+
6.25,1,8,3
|
|
125
|
+
6.14,3,1,3
|
|
126
|
+
6.48,3,1,3
|
|
127
|
+
6.02,1,1,3
|
|
128
|
+
6.03,1,1,3
|
|
129
|
+
6.13,3,1,3
|
|
130
|
+
6.07,3,1,3
|
|
131
|
+
6.09,3,1,3
|
|
132
|
+
5.66,5,5,5
|
|
133
|
+
6.2,3,1,1
|
|
134
|
+
6.13,1,1,3
|
|
135
|
+
5.99,1,1,3
|
|
136
|
+
6.13,1,1,1
|
|
137
|
+
6.01,7,1,3
|
|
138
|
+
6.11,1,1,3
|
|
139
|
+
6.17,1,1,1
|
|
140
|
+
6.19,3,1,1
|
|
141
|
+
6.18,1,1,3
|
|
142
|
+
6.09,1,1,3
|
|
143
|
+
5.74,5,5,5
|
|
144
|
+
6.19,7,1,3
|
|
145
|
+
6.29,1,1,3
|
|
146
|
+
6.25,1,1,1
|
|
147
|
+
6.24,1,1,1
|
|
148
|
+
6.33,3,1,1
|
|
149
|
+
6.23,3,1,3
|
|
150
|
+
6.35,1,8,1
|
|
151
|
+
6.32,1,1,1
|
|
152
|
+
6.37,1,1,1
|
|
153
|
+
6.21,1,1,1
|
|
154
|
+
5.88,5,5,5
|
|
155
|
+
6.2,1,1,1
|
|
156
|
+
6.58,1,8,1
|
|
157
|
+
6.44,1,8,1
|
|
158
|
+
6.48,1,8,1
|
|
159
|
+
7.4,2,8,1
|
|
160
|
+
6.38,1,7,1
|
|
161
|
+
6.44,1,8,1
|
|
162
|
+
6.65,1,8,1
|
|
163
|
+
6.86,1,8,1
|
|
164
|
+
6.71,1,3,1
|
|
165
|
+
6.1,5,5,5
|
|
166
|
+
6.88,7,3,1
|
|
167
|
+
6.72,7,3,1
|
|
168
|
+
6.3,7,3,1
|
|
169
|
+
6.65,1,7,1
|
|
170
|
+
6.34,1,8,1
|
|
171
|
+
7.22,1,3,1
|
|
172
|
+
6.5,1,3,3
|
|
173
|
+
6.52,1,3,1
|
|
174
|
+
6.53,7,3,1
|
|
175
|
+
6.43,7,3,1
|
|
176
|
+
5.89,5,5,5
|
|
177
|
+
6.5,7,3,3
|
|
178
|
+
6.48,7,3,3
|
|
179
|
+
6.5,7,3,1
|
|
180
|
+
6.38,1,7,1
|
|
181
|
+
6.18,3,1,3
|
|
182
|
+
6.39,1,7,1
|
|
183
|
+
6.45,1,8,1
|
|
184
|
+
6.86,2,7,1
|
|
185
|
+
6.29,2,7,1
|
|
186
|
+
6.49,1,7,1
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from typing import Sequence
|
|
5
|
+
from scipy.stats import f, ncf
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
def load_example_data():
|
|
11
|
+
file_path = Path(__file__).parent / "example_data" / "disease.csv"
|
|
12
|
+
df = pd.read_csv(file_path)
|
|
13
|
+
return df
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _plot_value(ax, interaction_df, ecological_df, value_fontsize=10):
|
|
17
|
+
length = len(interaction_df.index)
|
|
18
|
+
for i in range(length):
|
|
19
|
+
for j in range(length):
|
|
20
|
+
if not pd.isna(interaction_df.iloc[i, j]):
|
|
21
|
+
num = str(round(interaction_df.iloc[i, j], 2))
|
|
22
|
+
mark = num[-2:] if 3 == len(num) else num[-3:]
|
|
23
|
+
if 'Y'==ecological_df.iloc[i, j]:
|
|
24
|
+
ax.text(j, i, mark, ha="center", va="center", color="r", fontsize=value_fontsize)
|
|
25
|
+
else:
|
|
26
|
+
ax.text(j, i, mark, ha="center", va="center", color="k", fontsize=value_fontsize)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GeoDetector(object):
|
|
30
|
+
def __init__(self, df: pd.DataFrame, y: str, factors: Sequence[str]):
|
|
31
|
+
self.df = df
|
|
32
|
+
self.y = y
|
|
33
|
+
self.factors = factors
|
|
34
|
+
self._check_data(df, y, factors)
|
|
35
|
+
self.factor_df, self.interaction_df, self.ecological_df = None, None, None
|
|
36
|
+
|
|
37
|
+
def _check_data(self, df, y, factors):
|
|
38
|
+
for factor in factors:
|
|
39
|
+
if not factor in df.columns:
|
|
40
|
+
raise ValueError('Factor [{}] is not in data')
|
|
41
|
+
|
|
42
|
+
for factor in factors:
|
|
43
|
+
# 检查列的数据类型
|
|
44
|
+
if df[factor].dtype not in ['int64', 'int32', 'int16', 'int8',
|
|
45
|
+
'uint64', 'uint32', 'uint16', 'uint8',
|
|
46
|
+
'object', 'string']:
|
|
47
|
+
# 如果数据类型不是整型或字符型,发出警告
|
|
48
|
+
warnings.warn(f"Factor '{factor}' is not of type 'int' or 'str'.")
|
|
49
|
+
|
|
50
|
+
if y not in df.columns:
|
|
51
|
+
raise ValueError('Factor [{}] is not in data')
|
|
52
|
+
|
|
53
|
+
for factor in factors:
|
|
54
|
+
if y==factor:
|
|
55
|
+
raise ValueError("Y variable should not in Factor variables. ")
|
|
56
|
+
|
|
57
|
+
has_null = df.isnull().values.any()
|
|
58
|
+
if has_null:
|
|
59
|
+
raise ValueError("data hava some objects with value NULL")
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def _cal_ssw(self, df: pd.DataFrame, y, factor, extra_factor=None):
|
|
63
|
+
def cal_ssw(df: pd.DataFrame, y):
|
|
64
|
+
length = df.shape[0]
|
|
65
|
+
if length==1:
|
|
66
|
+
strataVar = 0
|
|
67
|
+
lamda_1st = np.square(df[y].values[0])
|
|
68
|
+
lamda_2nd = df[y].values[0]
|
|
69
|
+
else:
|
|
70
|
+
strataVar = (length-1) * df[y].var(ddof=1)
|
|
71
|
+
|
|
72
|
+
lamda_1st = np.square(df[y].values.mean())
|
|
73
|
+
lamda_2nd = np.sqrt(length) * df[y].values.mean()
|
|
74
|
+
return strataVar, lamda_1st, lamda_2nd
|
|
75
|
+
if extra_factor==None:
|
|
76
|
+
df2 = df[[y, factor]].groupby(factor).apply(cal_ssw, y=y)
|
|
77
|
+
else:
|
|
78
|
+
df2 = df[[y]+list(set([factor, extra_factor]))].groupby([factor, extra_factor]).apply(cal_ssw, y=y)
|
|
79
|
+
df2 = df2.apply(pd.Series)
|
|
80
|
+
df2 = df2.sum()
|
|
81
|
+
strataVarSum, lamda_1st_sum, lamda_2nd_sum = df2.values
|
|
82
|
+
return strataVarSum, lamda_1st_sum, lamda_2nd_sum
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def _cal_q(self, df, y, factor, extra_factor=None):
|
|
86
|
+
strataVarSum, lamda_1st_sum, lamda_2nd_sum = self._cal_ssw(df, y, factor, extra_factor)
|
|
87
|
+
TotalVar = (df.shape[0]-1)*df[y].var(ddof=1)
|
|
88
|
+
q = 1 - strataVarSum/TotalVar
|
|
89
|
+
return q, lamda_1st_sum, lamda_2nd_sum
|
|
90
|
+
|
|
91
|
+
def factor_dector(self):
|
|
92
|
+
self.factor_df = pd.DataFrame(index=["q statistic", "p value"], columns=self.factors, dtype="float32")
|
|
93
|
+
N_var = self.df[self.y].var(ddof=1)
|
|
94
|
+
N_popu = self.df.shape[0]
|
|
95
|
+
for factor in self.factors:
|
|
96
|
+
N_stra = self.df[factor].unique().shape[0]
|
|
97
|
+
q, lamda_1st_sum, lamda_2nd_sum = self._cal_q(self.df, self.y, factor)
|
|
98
|
+
|
|
99
|
+
#lamda value
|
|
100
|
+
lamda = (lamda_1st_sum - np.square(lamda_2nd_sum) / N_popu) / N_var
|
|
101
|
+
# F value
|
|
102
|
+
F_value = (N_popu - N_stra)* q / ((N_stra - 1)* (1 - q))
|
|
103
|
+
#p value
|
|
104
|
+
p_value = ncf.sf(F_value, N_stra - 1, N_popu - N_stra, nc=lamda)
|
|
105
|
+
|
|
106
|
+
self.factor_df.loc["q statistic", factor] = q
|
|
107
|
+
self.factor_df.loc["p value", factor] = p_value
|
|
108
|
+
return self.factor_df
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def _interaction_relationship(self, df):
|
|
112
|
+
out_df = pd.DataFrame(index=df.index, columns=df.columns)
|
|
113
|
+
length = len(df.index)
|
|
114
|
+
for i in range(length):
|
|
115
|
+
for j in range(i+1, length):
|
|
116
|
+
factor1, factor2 = df.index[i], df.index[j]
|
|
117
|
+
i_q = df.loc[factor2, factor1]
|
|
118
|
+
q1 = df.loc[factor1, factor1]
|
|
119
|
+
q2 = df.loc[factor2, factor2]
|
|
120
|
+
|
|
121
|
+
if (i_q <= q1 and i_q <= q2):
|
|
122
|
+
outputRls = "Weaken, nonlinear"
|
|
123
|
+
if (i_q < max(q1, q2) and i_q > min(q1, q2)):
|
|
124
|
+
outputRls = "Weaken, uni-"
|
|
125
|
+
if (i_q == (q1 + q2)):
|
|
126
|
+
outputRls = "Independent"
|
|
127
|
+
if (i_q > max(q1, q2)):
|
|
128
|
+
outputRls = "Enhance, bi-"
|
|
129
|
+
if (i_q > (q1 + q2)):
|
|
130
|
+
outputRls = "Enhance, nonlinear"
|
|
131
|
+
|
|
132
|
+
out_df.loc[factor2, factor1] = outputRls
|
|
133
|
+
return out_df
|
|
134
|
+
|
|
135
|
+
def interaction_detector(self, relationship=False):
|
|
136
|
+
self.interaction_df = pd.DataFrame(index=self.factors, columns=self.factors, dtype="float32")
|
|
137
|
+
length = len(self.factors)
|
|
138
|
+
for i in range(0, length):
|
|
139
|
+
for j in range(0, i+1):
|
|
140
|
+
q, _, _ = self._cal_q(self.df, self.y, self.factors[i], self.factors[j])
|
|
141
|
+
self.interaction_df.loc[self.factors[i], self.factors[j]] = q
|
|
142
|
+
|
|
143
|
+
if relationship:
|
|
144
|
+
self.interaction_relationship_df = self._interaction_relationship(self.interaction_df)
|
|
145
|
+
return self.interaction_df, self.interaction_relationship_df
|
|
146
|
+
return self.interaction_df
|
|
147
|
+
|
|
148
|
+
def ecological_detector(self):
|
|
149
|
+
self.ecological_df = pd.DataFrame(index=self.factors, columns=self.factors, dtype="float32")
|
|
150
|
+
length = len(self.factors)
|
|
151
|
+
for i in range(1, length):
|
|
152
|
+
ssw1, _, _ = self._cal_ssw(self.df, self.y, self.factors[i])
|
|
153
|
+
dfn = self.df[self.factors[i]].notna().sum()-1
|
|
154
|
+
for j in range(0, i):
|
|
155
|
+
ssw2, _, _ = self._cal_ssw(self.df, self.y, self.factors[j])
|
|
156
|
+
dfd = self.df[self.factors[j]].notna().sum()-1
|
|
157
|
+
fval = (dfn*(dfd-1)*ssw1)/(dfd*(dfn-1)*ssw2)
|
|
158
|
+
if fval<f.ppf(0.05, dfn, dfn):
|
|
159
|
+
self.ecological_df.loc[self.factors[i], self.factors[j]] = 'Y'
|
|
160
|
+
else:
|
|
161
|
+
self.ecological_df.loc[self.factors[i], self.factors[j]] = 'N'
|
|
162
|
+
return self.ecological_df
|
|
163
|
+
|
|
164
|
+
def plot(self, tick_fontsize=10, value_fontsize=10, colorbar_fontsize=10, show=True):
|
|
165
|
+
if isinstance(self.interaction_df, type(None)):
|
|
166
|
+
self.interaction_detector()
|
|
167
|
+
if isinstance(self.ecological_df, type(None)):
|
|
168
|
+
self.ecological_detector()
|
|
169
|
+
|
|
170
|
+
fig, ax = plt.subplots(constrained_layout=True)
|
|
171
|
+
|
|
172
|
+
im = ax.imshow(self.interaction_df.values, cmap="YlGnBu", vmin=0, vmax=1)
|
|
173
|
+
_plot_value(ax, self.interaction_df, self.ecological_df, value_fontsize=value_fontsize)
|
|
174
|
+
|
|
175
|
+
ax.set_xticks(np.arange(len(self.factors)))
|
|
176
|
+
ax.set_yticks(np.arange(len(self.factors)))
|
|
177
|
+
ax.spines['top'].set_visible(False)
|
|
178
|
+
ax.spines['right'].set_visible(False)
|
|
179
|
+
|
|
180
|
+
ax.set_xticklabels(self.factors, fontsize=tick_fontsize)
|
|
181
|
+
ax.set_yticklabels(self.factors, rotation=45, fontsize=tick_fontsize)
|
|
182
|
+
ax.tick_params(axis='y', pad=0.1)
|
|
183
|
+
|
|
184
|
+
colorbar = fig.colorbar(im, ax=ax, shrink=0.9, pad=0.01, aspect=25, extend="both")
|
|
185
|
+
colorbar.ax.tick_params(labelsize=colorbar_fontsize)
|
|
186
|
+
|
|
187
|
+
if show:
|
|
188
|
+
plt.show()
|
|
189
|
+
return ax
|
|
190
|
+
else:
|
|
191
|
+
return ax
|