PineBioML 1.2.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.
@@ -0,0 +1,763 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Union
3
+
4
+ import pandas as pd
5
+ import numpy as np
6
+
7
+ import matplotlib.pyplot as plt
8
+ from matplotlib.colors import Normalize
9
+ from seaborn import scatterplot, heatmap, pairplot, color_palette
10
+
11
+ from sklearn.decomposition import PCA
12
+ from sklearn.cross_decomposition import PLSRegression
13
+ from sklearn.preprocessing import OneHotEncoder
14
+ import sklearn.metrics as metrics
15
+
16
+ from umap import UMAP
17
+
18
+
19
+ class basic_plot(ABC):
20
+ """
21
+ the base class of plots.
22
+ Using make_figure(x, y) to generate a figure.
23
+
24
+ """
25
+
26
+ def __init__(self,
27
+ prefix: str = "",
28
+ save_path: str = "./",
29
+ save_fig: bool = False,
30
+ show_fig: bool = True):
31
+ """
32
+
33
+ Args:
34
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
35
+ save_path (str, optional): the path to export the figure. Defaults to "./".
36
+ save_fig (bool, optional): whether to export the figure or not. Defaults to False.
37
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
38
+ """
39
+
40
+ self.prefix = prefix
41
+ self.save_path = save_path
42
+ self.save_fig = save_fig
43
+ self.show_fig = show_fig
44
+
45
+ @abstractmethod
46
+ def save_name(self):
47
+ pass
48
+
49
+ def reference(self) -> dict[str, str]:
50
+ """
51
+ This function will return reference of this method in python dict.
52
+ If you want to access it in PineBioML api document, then click on the >Expand source code
53
+
54
+ Returns:
55
+ dict[str, str]: a dict of reference.
56
+ """
57
+ refer = {
58
+ "matplotlib document": "https://matplotlib.org/",
59
+ "seaborn document": "https://seaborn.pydata.org/"
60
+ }
61
+
62
+ return refer
63
+
64
+ @abstractmethod
65
+ def draw(self, x: pd.DataFrame, y: pd.Series = None):
66
+ """
67
+ How and what to draw should be implemented in here.
68
+
69
+ Args:
70
+ x (pd.DataFrame): feature
71
+ y (pd.Series, optional): label. Defaults to None.
72
+ """
73
+ pass
74
+
75
+ def make_figure(self, x: pd.DataFrame, y: pd.Series = None):
76
+ """
77
+ 1. draw(x, y)
78
+ 2. To save or to show the result.
79
+
80
+ Args:
81
+ x (pd.DataFrame): features
82
+ y (pd.Series, optional): label. Defaults to None.
83
+ """
84
+
85
+ self.draw(x, y)
86
+
87
+ if self.save_fig:
88
+ plt.savefig(self.save_path + self.save_name(), bbox_inches='tight')
89
+ if self.show_fig:
90
+ plt.show()
91
+ else:
92
+ plt.clf()
93
+
94
+
95
+ class pca_plot(basic_plot):
96
+ """
97
+ Calling pca_plot().make_figure(x) or pca_plot().make_figure(x, y) to draw a pca plot of x with n_pc components.
98
+
99
+ """
100
+
101
+ def __init__(self,
102
+ n_pc: int = 4,
103
+ discrete_legend: bool = True,
104
+ prefix: str = "",
105
+ save_path: str = "./output/images/",
106
+ save_fig: bool = True,
107
+ show_fig: bool = True):
108
+ """
109
+
110
+ Args:
111
+ n_pc (int, optional): number of precipal compoment to plot. Defaults to 4.
112
+ discrete_legend (bool, optional): To color the plot based on y in discrete hue or continuous color bar. If y is continuous, then you should set it to False. Defaults to True.
113
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
114
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
115
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
116
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
117
+ """
118
+ super().__init__(prefix=prefix,
119
+ save_path=save_path,
120
+ save_fig=save_fig,
121
+ show_fig=show_fig)
122
+ self.n_pc = n_pc
123
+ self.discrete_legend = discrete_legend
124
+ self.name = "PCA"
125
+
126
+ def save_name(self) -> str:
127
+ """
128
+ Returns:
129
+ str: {prefix} PCA plot
130
+ """
131
+ return "{} {} plot".format(self.prefix, self.name)
132
+
133
+ def reference(self) -> dict[str, str]:
134
+ """
135
+ This function will return reference of this method in python dict.
136
+ If you want to access it in PineBioML api document, then click on the >Expand source code
137
+
138
+ Returns:
139
+ dict[str, str]: a dict of reference.
140
+ """
141
+ refer = super().reference()
142
+ refer[
143
+ self.name +
144
+ " document"] = "https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html"
145
+
146
+ return refer
147
+
148
+ def draw(self, x: pd.DataFrame, y: pd.Series = None):
149
+ """
150
+ Using x to draw a pca plot. The difference between pca_plot().draw(x) and pca_plot().draw(x, y) is that:
151
+ - pca_plot().draw(x) will give a normal pca plot.
152
+ - pca_plot().draw(x, y) will coloring the points on the figure based on y. Set discrete_legend to True if y is continuous, False otherwise.
153
+
154
+ What we do here is:
155
+ 1. standardize x
156
+ 2. fit a PCA(n_pc) on x and storing the result in pd.DataFrame
157
+ 3. Decide how to color the plots by various cases of y and discrete_legend.
158
+
159
+ Args:
160
+ x (pd.DataFrame): feature
161
+ y (pd.Series, optional): label. Defaults to None.
162
+ """
163
+
164
+ # calculate pca and store in pd.DataFrame
165
+ pcs = PCA(self.n_pc).fit_transform((x - x.mean()) / (x.std() + 1e-4))
166
+ pcs = pd.DataFrame(
167
+ pcs,
168
+ index=x.index,
169
+ columns=["pc_" + str(i + 1) for i in range(self.n_pc)])
170
+
171
+ if y is None:
172
+ y_name = None
173
+ else:
174
+ # add y into the DataFrame for coloring the data points
175
+ y_name = "y" if y.name is None else y.name
176
+ pcs[y_name] = y
177
+
178
+ if self.discrete_legend:
179
+ # discrete legend
180
+ plot = pairplot(data=pcs, hue=y_name)
181
+ elif not y is None:
182
+ # color bar
183
+ cmap = color_palette('ch:', as_cmap=True)
184
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=Normalize())
185
+ sm.set_array([])
186
+ plot = pairplot(data=pcs, hue=y_name)
187
+ plot.legend.remove()
188
+
189
+ cbar = plt.colorbar(sm, ax=plot.axes)
190
+ cbar.set_label(y_name)
191
+ else:
192
+ # vanilla
193
+ plot = pairplot(data=pcs)
194
+
195
+ plot.figure.suptitle("{} {} Scatter plot".format(
196
+ self.prefix, self.name),
197
+ y=1.01)
198
+
199
+
200
+ class pls_plot(basic_plot):
201
+ """
202
+ PLS-DA is a supervied method in dimension decomposition.
203
+ This function will plot the result of PLS-DA of given data.
204
+
205
+ Using pls_plot().make_figure(x, y) to generate a figure.
206
+
207
+ Warning: PLS-DA is a limited tool in multi-class classification and unlinear regression problem.
208
+
209
+ """
210
+
211
+ def __init__(self,
212
+ is_classification: bool,
213
+ discrete_legend: bool = True,
214
+ prefix: str = "",
215
+ save_path: str = "./output/images/",
216
+ save_fig: bool = True,
217
+ show_fig: bool = True):
218
+ """
219
+
220
+ Args:
221
+ is_classification (bool): If (x, y) is a classification task, then set is_classification to True.
222
+ discrete_legend (bool, optional): To color the plot based on y in discrete hue or continuous color bar. If y is continuous, then you should set it to False. Defaults to True.
223
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
224
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
225
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
226
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
227
+ """
228
+ super().__init__(prefix=prefix,
229
+ save_path=save_path,
230
+ save_fig=save_fig,
231
+ show_fig=show_fig)
232
+ self.discrete_legend = discrete_legend
233
+ self.is_classification = is_classification
234
+ self.name = "PLS"
235
+
236
+ def save_name(self):
237
+ return "{} {} plot".format(self.prefix, self.name)
238
+
239
+ def reference(self) -> dict[str, str]:
240
+ """
241
+ This function will return reference of this method in python dict.
242
+ If you want to access it in PineBioML api document, then click on the >Expand source code
243
+
244
+ Returns:
245
+ dict[str, str]: a dict of reference.
246
+ """
247
+ refer = super().reference()
248
+ refer[
249
+ self.name +
250
+ " document"] = "https://scikit-learn.org/stable/modules/generated/sklearn.cross_decomposition.PLSRegression.html"
251
+
252
+ return refer
253
+
254
+ def draw(self, x: pd.DataFrame, y: pd.Series):
255
+ """
256
+ What we do here is:
257
+ 1. If is_classification => one-hot encode the y.
258
+ 2. Do PLS-DA
259
+ 3. Decide how to color the plots by various cases of y and discrete_legend.
260
+
261
+ Args:
262
+ x (pd.DataFrame): features
263
+ y (pd.Series, optional): label.
264
+
265
+ Raises:
266
+ TypeError: _description_
267
+ """
268
+ # one hot encoder for classification
269
+ if self.is_classification:
270
+ OneHot_y = OneHotEncoder(sparse_output=False).fit_transform(
271
+ y.to_numpy().reshape(-1, 1))
272
+ # fit pls regression
273
+ pls = PLSRegression(n_components=2).fit(x, OneHot_y)
274
+ else:
275
+ if y.dtype == "O":
276
+ raise TypeError(
277
+ "the dtype of y can't be object while is_classification was setting to False, which means it is a regression task and y should be float or int."
278
+ )
279
+ # fit pls regression
280
+ pls = PLSRegression(n_components=2).fit(x, y)
281
+
282
+ # project x
283
+ plscs = pls.transform(x)
284
+ plscs = pd.DataFrame(
285
+ plscs,
286
+ index=x.index,
287
+ columns=[self.name + " componet 1", self.name + " componet 2"])
288
+
289
+ if y is None:
290
+ y_name = None
291
+ else:
292
+ # add y into the DataFrame for coloring the data points
293
+ y_name = "y" if y.name is None else y.name
294
+ plscs[y_name] = y
295
+
296
+ if self.discrete_legend:
297
+ # discrete legend
298
+ plot = scatterplot(data=plscs,
299
+ x=self.name + " componet 1",
300
+ y=self.name + " componet 2",
301
+ hue=y_name)
302
+ plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
303
+ elif not y is None:
304
+ # color bar
305
+ cmap = color_palette('ch:', as_cmap=True)
306
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=Normalize())
307
+ plot = scatterplot(data=plscs,
308
+ x=self.name + " componet 1",
309
+ y=self.name + " componet 2",
310
+ hue=y_name,
311
+ hue_norm=sm.norm,
312
+ palette=cmap,
313
+ legend=False)
314
+ cbar = plt.colorbar(sm, ax=plt.gca())
315
+ cbar.set_label(y_name)
316
+ else:
317
+ # vanilla
318
+ plot = scatterplot(data=plscs,
319
+ x=self.name + " componet 1",
320
+ y=self.name + " componet 2")
321
+
322
+ plot.set_title("{} {} Scatter plot".format(self.prefix, self.name))
323
+
324
+
325
+ class umap_plot(basic_plot):
326
+ """
327
+ Umap is a unsupervissed method to reduce the number of dimension of given data. It's based on manifold learning and it has uncertainty.
328
+
329
+ Using umap_plot().make_figure(x) or umap_plot().make_figure(x, y) to generate a Umap plot.
330
+
331
+ Warning: Only the clustering tendency is reliable on the graph.
332
+ """
333
+
334
+ def __init__(self,
335
+ discrete_legend=True,
336
+ prefix="",
337
+ save_path="./output/images/",
338
+ save_fig=True,
339
+ show_fig=True):
340
+ """
341
+
342
+ Args:
343
+ discrete_legend (bool, optional): To color the plot based on y in discrete hue or continuous color bar. If y is continuous, then you should set it to False. Defaults to True.
344
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
345
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
346
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
347
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
348
+ """
349
+ super().__init__(prefix=prefix,
350
+ save_path=save_path,
351
+ save_fig=save_fig,
352
+ show_fig=show_fig)
353
+ self.discrete_legend = discrete_legend
354
+ self.name = "UMAP"
355
+
356
+ def save_name(self):
357
+ return "{} {} plot".format(self.prefix, self.name)
358
+
359
+ def reference(self) -> dict[str, str]:
360
+ """
361
+ This function will return reference of this method in python dict.
362
+ If you want to access it in PineBioML api document, then click on the >Expand source code
363
+
364
+ Returns:
365
+ dict[str, str]: a dict of reference.
366
+ """
367
+ refer = super().reference()
368
+ refer[self.name +
369
+ " document"] = "https://umap-learn.readthedocs.io/en/latest/"
370
+ refer[
371
+ self.name +
372
+ " publication"] = "https://joss.theoj.org/papers/10.21105/joss.00861"
373
+
374
+ return refer
375
+
376
+ def draw(self, x: pd.DataFrame, y: pd.Series = None):
377
+ """
378
+ Using Umap do transform x into 2D plane. The difference between umap_plot().draw(x) and umap_plot().draw(x, y) is that:
379
+ - umap_plot().draw(x) will give a normal umap scatter plot.
380
+ - umap_plot().draw(x, y) will coloring the points on the figure based on y. Set discrete_legend to True if y is continuous, False otherwise.
381
+
382
+ What we do here is:
383
+ 1. standardize x
384
+ 2. fit a UMAP(n_neighbors=np.log2(n_sample) on x and storing the result in pd.DataFrame
385
+ 3. Decide how to color the plots by various cases of y and discrete_legend.
386
+
387
+ Args:
388
+ x (pd.DataFrame): feature
389
+ y (pd.Series, optional): label. Defaults to None.
390
+ """
391
+
392
+ # fit a umap for x, you can change n_neighbors to any other feasible value.
393
+ umapcs = UMAP(n_neighbors=round(np.log2(x.shape[0])),
394
+ n_components=2).fit_transform(
395
+ (x - x.mean()) / (x.std() + 1e-6))
396
+ umapcs = pd.DataFrame(
397
+ umapcs,
398
+ index=x.index,
399
+ columns=[self.name + " dimension 1", self.name + " dimension 2"])
400
+
401
+ if y is None:
402
+ y_name = None
403
+ else:
404
+ # add y into the DataFrame for coloring the data points
405
+ y_name = "y" if y.name is None else y.name
406
+ umapcs[y_name] = y
407
+
408
+ if self.discrete_legend:
409
+ # discrete legend
410
+ plot = scatterplot(data=umapcs,
411
+ x=self.name + " dimension 1",
412
+ y=self.name + " dimension 2",
413
+ hue=y_name)
414
+ plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
415
+ elif not y is None:
416
+ # color bar
417
+ cmap = color_palette('ch:', as_cmap=True)
418
+ sm = plt.cm.ScalarMappable(cmap=cmap, norm=Normalize())
419
+ plot = scatterplot(data=umapcs,
420
+ x=self.name + " dimension 1",
421
+ y=self.name + " dimension 2",
422
+ hue=y_name,
423
+ hue_norm=sm.norm,
424
+ palette=cmap,
425
+ legend=False)
426
+ cbar = plt.colorbar(sm, ax=plt.gca())
427
+ cbar.set_label(y_name)
428
+ else:
429
+ # vanilla
430
+ plot = scatterplot(data=umapcs,
431
+ x=self.name + " dimension 1",
432
+ y=self.name + " dimension 2")
433
+
434
+ plot.set_title("{} {} Scatter plot".format(self.prefix, self.name))
435
+
436
+
437
+ class corr_heatmap_plot(basic_plot):
438
+ """
439
+ plot correlation coefficients of given data in heatmap.
440
+
441
+ Using corr_heatmap_plot().make_figure(x) or corr_heatmap_plot().make_figure(x, y) to generate a figure.
442
+ """
443
+
444
+ def __init__(self,
445
+ prefix="",
446
+ save_path="./output/images/",
447
+ save_fig=True,
448
+ show_fig=True):
449
+ """
450
+
451
+ Args:
452
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
453
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
454
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
455
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
456
+ """
457
+ super().__init__(prefix=prefix,
458
+ save_path=save_path,
459
+ save_fig=save_fig,
460
+ show_fig=show_fig)
461
+ self.name = "Correlation Heatmap"
462
+
463
+ def save_name(self):
464
+ return "{} {} plot".format(self.prefix, self.name)
465
+
466
+ def draw(self, x: pd.DataFrame, y: pd.Series = None):
467
+ """
468
+ what we do here is:
469
+ 1. add y into x as a new column if y is not None.
470
+ 2. compute correlation between x's columns.
471
+ 3. drawint the result in heatmap.
472
+
473
+ Args:
474
+ x (pd.DataFrame): feature
475
+ y (pd.Series, optional): Label. Defaults to None.
476
+ """
477
+
478
+ data = x.copy()
479
+ if y is None:
480
+ y_name = None
481
+ else:
482
+ # add y into the DataFrame for coloring the data points
483
+ y_name = "y" if y.name is None else y.name
484
+ data[y_name] = y
485
+
486
+ plot = heatmap(data.corr(), vmin=-1, vmax=1, cmap='RdBu')
487
+
488
+ plot.set_title("{} {}".format(self.prefix, self.name))
489
+
490
+
491
+ class confusion_matrix_plot(basic_plot):
492
+ """
493
+ plot confusion matrix of given ground true label and predictions.
494
+ """
495
+
496
+ def __init__(self,
497
+ prefix="",
498
+ save_path="./output/images/",
499
+ save_fig=True,
500
+ show_fig=True):
501
+ """
502
+
503
+ Args:
504
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
505
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
506
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
507
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
508
+
509
+ Todo:
510
+ value normalize by y_true and crowding problem in multi-class classification.
511
+ """
512
+ super().__init__(prefix=prefix,
513
+ save_path=save_path,
514
+ save_fig=save_fig,
515
+ show_fig=show_fig)
516
+ self.name = "Confusion Matrix"
517
+ self.normalize = None
518
+
519
+ def save_name(self):
520
+ return "{} {}".format(self.prefix, self.name)
521
+
522
+ def draw(self, y_true: pd.Series, y_pred: pd.Series):
523
+ """
524
+ plot the confusion matrix using y_true and y_pred.
525
+
526
+ Args:
527
+ y_true (pd.Series): Ground true
528
+ y_pred (pd.Series): prediction from an estimator.
529
+ """
530
+
531
+ plot = metrics.ConfusionMatrixDisplay.from_predictions(
532
+ y_true,
533
+ y_pred,
534
+ normalize=self.normalize,
535
+ xticks_rotation="vertical")
536
+ plot.ax_.set_title("{} {}".format(self.prefix, self.name))
537
+
538
+
539
+ class roc_plot(basic_plot):
540
+ """
541
+ Depends on how the number of class in y_true and, pos_label, this function will plot a roc curve or several curves of given data.
542
+ """
543
+
544
+ def __init__(self,
545
+ pos_label: Union[str, int, float] = None,
546
+ prefix="",
547
+ save_path="./output/images/",
548
+ save_fig=True,
549
+ show_fig=True):
550
+ """
551
+
552
+ Args:
553
+ pos_label (Union[str, int, float], optional): If not None, the result will be pos_label vs rest (ovr) roc curve. Defaults to None.
554
+ prefix (str, optional): the describe or title for the plot. the prefix will be added into the title of plot and saving name. Defaults to "".
555
+ save_path (str, optional): the path to export the figure. Defaults to "./output/images/".
556
+ save_fig (bool, optional): whether to export the figure or not. Defaults to True.
557
+ show_fig (bool, optional): whether to show the figure or not. Defaults to True.
558
+ """
559
+ super().__init__(prefix=prefix,
560
+ save_path=save_path,
561
+ save_fig=save_fig,
562
+ show_fig=show_fig)
563
+ self.name = "ROC Curve"
564
+ self.pos_label = pos_label
565
+
566
+ def save_name(self):
567
+ return "{} {}".format(self.prefix, self.name)
568
+
569
+ def draw(self, y_true: pd.Series, y_pred_prob: pd.DataFrame):
570
+ """
571
+ draw roc curve
572
+
573
+ Args:
574
+ y_true (pd.Series): Ground true
575
+ y_pred_prob (pd.DataFrame): The probability that model predicted for each class. y_pred_prob should have shape (n_samples, n_class)
576
+ """
577
+
578
+ # ROC curve
579
+ if len(y_true.value_counts()) <= 2:
580
+ # binary ROC curve
581
+ fpr, tpr, threshold = metrics.roc_curve(y_true,
582
+ y_pred_prob.iloc[:, 1],
583
+ pos_label=self.pos_label)
584
+ roc_auc = metrics.auc(fpr, tpr)
585
+ plt.plot(fpr, tpr, 'b', label='AUC = %0.3f' % roc_auc)
586
+ plt.title(self.prefix + 'ROC curve')
587
+
588
+ else:
589
+ # one vs rest ROC curve
590
+ for label in y_pred_prob.columns:
591
+ label_prob = y_pred_prob[label]
592
+
593
+ fpr, tpr, threshold = metrics.roc_curve(
594
+ y_true == label, label_prob)
595
+ roc_auc = metrics.auc(fpr, tpr)
596
+
597
+ plt.plot(fpr, tpr, label=str(label) + ' (AUC=%0.3f)' % roc_auc)
598
+ plt.title(self.prefix + 'one vs rest ROC curves')
599
+
600
+ plt.plot([0, 1], [0, 1], 'r--')
601
+ plt.xlim([0, 1])
602
+ plt.ylim([0, 1])
603
+ plt.ylabel('True Positive Rate')
604
+ plt.xlabel('False Positive Rate')
605
+ plt.legend(loc='lower right')
606
+
607
+
608
+ def data_overview(input_x: pd.DataFrame,
609
+ y: pd.Series,
610
+ is_classification: bool = True,
611
+ discrete_legend=True,
612
+ n_pc=4,
613
+ prefix="",
614
+ save_fig=True,
615
+ save_path="./output/images/",
616
+ show_fig=True):
617
+ """
618
+ Make a glance to data. Specifically it will:
619
+ 1. make a pca plot.
620
+ 2. make a pls plot.
621
+ 3. make a Umap plot.
622
+ 4. make a correlation heatmap.
623
+
624
+ Args:
625
+ input_x (pd.DataFrame): the input feature (or the explanatory variables).
626
+ y (pd.Series): the target variable (or the response variable).
627
+ is_classification (bool, optional): whether the task to fit y is a classification task or a regression task. Defaults to True.
628
+ discrete_legend (bool, optional): whether to use a discrete legend, otherwise a color bar will be used. If is_classification is True, then discrete_legend will forced to be Ture. Defaults to True.
629
+ prefix (str, optional): the name or the description to the task. It will be add into the title and the export figure name. Defaults to "".
630
+ save_fig (bool, optional): To export the figure or not. Defaults to True.
631
+ save_path (str, optional): The export path of the figure. Defaults to "./output/images/".
632
+ show_fig (bool, optional): To show the figure before export or not. Defaults to True.
633
+ """
634
+
635
+ x = input_x.copy()
636
+ if is_classification:
637
+ discrete_legend = True
638
+
639
+ # PCA
640
+ pca_plot(n_pc=n_pc,
641
+ discrete_legend=discrete_legend,
642
+ prefix=prefix,
643
+ save_path=save_path,
644
+ save_fig=save_fig,
645
+ show_fig=show_fig).make_figure(x, y)
646
+
647
+ # PLS
648
+ pls_plot(is_classification=is_classification,
649
+ discrete_legend=discrete_legend,
650
+ prefix=prefix,
651
+ save_path=save_path,
652
+ save_fig=save_fig,
653
+ show_fig=show_fig).make_figure(x, y)
654
+
655
+ # UMAP
656
+ umap_plot(discrete_legend=discrete_legend,
657
+ prefix=prefix,
658
+ save_path=save_path,
659
+ save_fig=save_fig,
660
+ show_fig=show_fig).make_figure(x, y)
661
+
662
+ # Correlation heatmap
663
+ if y.dtype == "O":
664
+ corr_heatmap_plot(prefix=prefix,
665
+ save_path=save_path,
666
+ save_fig=save_fig,
667
+ show_fig=show_fig).make_figure(x)
668
+ else:
669
+ corr_heatmap_plot(prefix=prefix,
670
+ save_path=save_path,
671
+ save_fig=save_fig,
672
+ show_fig=show_fig).make_figure(x, y)
673
+
674
+
675
+ def classification_summary(y_true,
676
+ y_pred_prob,
677
+ target_label=None,
678
+ prefix="",
679
+ save_path="./output/images/",
680
+ save_fig=True,
681
+ show_fig=True):
682
+ """
683
+ Give a classification summary, including:
684
+ 1. recall, precision, f1 and accuracy.
685
+ 2. confusion matrix.
686
+ 3. ROC curve.
687
+
688
+ Args:
689
+ y_true (pandas.Series or a 1D array): Bool, the label
690
+ y_pred_prob (pandas.Series or a 1D array): float in [0, 1]. prediction from model
691
+ Todo:
692
+ 1. support to multi-class classification(on going)
693
+ 2. the label matching between y_true and y_pred
694
+ 3. support to regression
695
+ """
696
+ y_pred = y_pred_prob.idxmax(axis=1)
697
+ print("\n", prefix)
698
+ print(metrics.classification_report(y_true, y_pred))
699
+
700
+ if not target_label is None:
701
+ # binary classification
702
+ confusion_scores = metrics.classification_report(
703
+ y_true == target_label, y_pred == target_label, output_dict=True)
704
+ sensitivity = confusion_scores["True"]["recall"]
705
+ specificity = confusion_scores["False"]["recall"]
706
+
707
+ print("sensitivity: {:.3f}".format(sensitivity))
708
+ print("specificity: {:.3f}".format(specificity))
709
+
710
+ # confusion matrix
711
+ confusion_matrix_plot(prefix=prefix,
712
+ save_path=save_path,
713
+ show_fig=show_fig,
714
+ save_fig=save_fig).make_figure(y_true, y_pred)
715
+
716
+ # roc cuve
717
+ roc_plot(pos_label=target_label,
718
+ prefix=prefix,
719
+ save_path=save_path,
720
+ show_fig=show_fig,
721
+ save_fig=save_fig).make_figure(y_true, y_pred_prob)
722
+
723
+
724
+ def regression_summary(y_true: pd.Series,
725
+ y_pred: pd.Series,
726
+ x: pd.DataFrame = None,
727
+ prefix="",
728
+ save_path="./output/images/",
729
+ save_fig=True,
730
+ show_fig=True):
731
+ """
732
+ 1. compute rmse, r square and mape if y is all positive.
733
+ 2. feature pca residual plot if x is not None.
734
+
735
+ Args:
736
+ y_true (pd.Series): Ground true
737
+ y_pred (pd.Series): The estimates from model.
738
+ x (pd.DataFrame, optional): features. If not None, it will be used to plot a feature pca residual plot. Defaults to None.
739
+ prefix (str, optional): prefix of figure title. Defaults to "".
740
+ save_path (str, optional): The export path of the figure. Defaults to "./output/images/".
741
+ save_fig (bool, optional): To export the figure or not. Defaults to True.
742
+ show_fig (bool, optional): To show the figure before export or not. Defaults to True.
743
+ """
744
+ residual = y_true - y_pred
745
+
746
+ print("\n", prefix, " performance:")
747
+ print(" r2 : {:.3f}".format(
748
+ metrics.root_mean_squared_error(y_true, y_pred)))
749
+ print(" rmse : {:.3f}".format(metrics.r2_score(y_true, y_pred)))
750
+ print(" mae : {:.3f}".format(
751
+ metrics.mean_absolute_error(y_true, y_pred)))
752
+ if (y_true > 0).all():
753
+ print(" mape : {:.3f}".format(
754
+ metrics.mean_absolute_percentage_error(y_true, y_pred)))
755
+ print(" support: {:.3f}".format(len(y_true)))
756
+
757
+ if not x is None:
758
+ pca_plot(n_pc=2,
759
+ discrete_legend=False,
760
+ prefix=prefix + " Residual",
761
+ save_path=save_path,
762
+ save_fig=save_fig,
763
+ show_fig=show_fig).make_figure(x, residual)