absfuyu 4.2.0__py3-none-any.whl → 5.0.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.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +4 -4
- absfuyu/__main__.py +13 -1
- absfuyu/cli/color.py +7 -0
- absfuyu/cli/do_group.py +0 -35
- absfuyu/cli/tool_group.py +5 -5
- absfuyu/config/__init__.py +17 -34
- absfuyu/core/__init__.py +49 -0
- absfuyu/core/baseclass.py +299 -0
- absfuyu/core/baseclass2.py +165 -0
- absfuyu/core/decorator.py +67 -0
- absfuyu/core/docstring.py +163 -0
- absfuyu/core/dummy_cli.py +67 -0
- absfuyu/core/dummy_func.py +47 -0
- absfuyu/dxt/__init__.py +42 -0
- absfuyu/dxt/dictext.py +201 -0
- absfuyu/dxt/dxt_support.py +79 -0
- absfuyu/dxt/intext.py +586 -0
- absfuyu/dxt/listext.py +508 -0
- absfuyu/dxt/strext.py +530 -0
- absfuyu/{extensions → extra}/__init__.py +2 -2
- absfuyu/extra/beautiful.py +251 -0
- absfuyu/{extensions → extra}/data_analysis.py +51 -82
- absfuyu/fun/__init__.py +110 -135
- absfuyu/fun/tarot.py +9 -17
- absfuyu/game/__init__.py +6 -0
- absfuyu/game/game_stat.py +6 -0
- absfuyu/game/sudoku.py +7 -1
- absfuyu/game/tictactoe.py +12 -5
- absfuyu/game/wordle.py +14 -8
- absfuyu/general/__init__.py +6 -79
- absfuyu/general/content.py +22 -36
- absfuyu/general/generator.py +17 -42
- absfuyu/general/human.py +108 -228
- absfuyu/general/shape.py +1334 -0
- absfuyu/logger.py +8 -13
- absfuyu/pkg_data/__init__.py +136 -99
- absfuyu/pkg_data/deprecated.py +133 -0
- absfuyu/sort.py +6 -130
- absfuyu/tools/__init__.py +2 -2
- absfuyu/tools/checksum.py +33 -22
- absfuyu/tools/converter.py +51 -48
- absfuyu/tools/keygen.py +25 -30
- absfuyu/tools/obfuscator.py +246 -112
- absfuyu/tools/passwordlib.py +99 -29
- absfuyu/tools/shutdownizer.py +68 -47
- absfuyu/tools/web.py +2 -9
- absfuyu/util/__init__.py +15 -15
- absfuyu/util/api.py +10 -15
- absfuyu/util/json_method.py +7 -24
- absfuyu/util/lunar.py +3 -9
- absfuyu/util/path.py +22 -27
- absfuyu/util/performance.py +43 -67
- absfuyu/util/shorten_number.py +65 -14
- absfuyu/util/zipped.py +9 -15
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/METADATA +41 -14
- absfuyu-5.0.0.dist-info/RECORD +68 -0
- absfuyu/core.py +0 -57
- absfuyu/everything.py +0 -32
- absfuyu/extensions/beautiful.py +0 -188
- absfuyu/fun/WGS.py +0 -134
- absfuyu/general/data_extension.py +0 -1796
- absfuyu/tools/stats.py +0 -226
- absfuyu/util/pkl.py +0 -67
- absfuyu-4.2.0.dist-info/RECORD +0 -59
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/WHEEL +0 -0
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absfuyu: Beautiful
|
|
3
|
+
------------------
|
|
4
|
+
A decorator that makes output more beautiful
|
|
5
|
+
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 18/02/2025 (dd/mm/yyyy)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Module level
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
|
+
__all__ = [
|
|
13
|
+
"BeautifulOutput",
|
|
14
|
+
"print",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Library
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
import time
|
|
21
|
+
import tracemalloc
|
|
22
|
+
from collections.abc import Callable
|
|
23
|
+
from functools import wraps
|
|
24
|
+
from typing import Any, Literal, NamedTuple, ParamSpec, TypeVar
|
|
25
|
+
|
|
26
|
+
BEAUTIFUL_MODE = False
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
from rich.align import Align
|
|
30
|
+
from rich.console import Console, Group
|
|
31
|
+
from rich.panel import Panel
|
|
32
|
+
from rich.table import Table
|
|
33
|
+
from rich.text import Text
|
|
34
|
+
except ImportError:
|
|
35
|
+
from subprocess import run
|
|
36
|
+
|
|
37
|
+
from absfuyu.config import ABSFUYU_CONFIG
|
|
38
|
+
|
|
39
|
+
if ABSFUYU_CONFIG._get_setting("auto-install-extra").value:
|
|
40
|
+
cmd = "python -m pip install -U absfuyu[beautiful]".split()
|
|
41
|
+
run(cmd)
|
|
42
|
+
else:
|
|
43
|
+
raise SystemExit("This feature is in absfuyu[beautiful] package") # noqa: B904
|
|
44
|
+
else:
|
|
45
|
+
BEAUTIFUL_MODE = True
|
|
46
|
+
|
|
47
|
+
# Setup
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# rich's console.print wrapper
|
|
50
|
+
console = Console(color_system="auto", tab_size=4)
|
|
51
|
+
print = console.print
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Type
|
|
55
|
+
# ---------------------------------------------------------------------------
|
|
56
|
+
P = ParamSpec("P") # Parameter type
|
|
57
|
+
R = TypeVar("R") # Return type - Can be anything
|
|
58
|
+
T = TypeVar("T", bound=type) # Type type - Can be any subtype of `type`
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# Class
|
|
62
|
+
# ---------------------------------------------------------------------------
|
|
63
|
+
class PerformanceOutput(NamedTuple):
|
|
64
|
+
runtime: float
|
|
65
|
+
current_memory: int
|
|
66
|
+
peak_memory: int
|
|
67
|
+
|
|
68
|
+
def to_text(self) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Beautify the result and ready to print
|
|
71
|
+
"""
|
|
72
|
+
out = (
|
|
73
|
+
f"Memory usage: {self.current_memory / 10**6:,.6f} MB\n"
|
|
74
|
+
f"Peak memory usage: {self.peak_memory / 10**6:,.6f} MB\n"
|
|
75
|
+
f"Time elapsed: {self.runtime:,.6f} s"
|
|
76
|
+
)
|
|
77
|
+
return out
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class BeautifulOutput:
|
|
81
|
+
"""A decorator that makes output more beautiful"""
|
|
82
|
+
|
|
83
|
+
def __init__(
|
|
84
|
+
self,
|
|
85
|
+
layout: Literal[1, 2, 3, 4, 5, 6] = 1,
|
|
86
|
+
include_header: bool = True,
|
|
87
|
+
include_footer: bool = True,
|
|
88
|
+
alternate_footer: bool = False,
|
|
89
|
+
) -> None:
|
|
90
|
+
"""
|
|
91
|
+
Show function's signature and measure memory usage
|
|
92
|
+
|
|
93
|
+
Parameters
|
|
94
|
+
----------
|
|
95
|
+
layout : Literal[1, 2, 3, 4, 5, 6], optional
|
|
96
|
+
Layout to show, by default ``1``
|
|
97
|
+
|
|
98
|
+
include_header : bool, optional
|
|
99
|
+
Include header with function's signature, by default ``True``
|
|
100
|
+
|
|
101
|
+
include_footer : bool, optional
|
|
102
|
+
Include footer, by default ``True``
|
|
103
|
+
|
|
104
|
+
alternate_footer : bool, optional
|
|
105
|
+
Alternative style of footer, by default ``False``
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
Usage
|
|
109
|
+
-----
|
|
110
|
+
Use this as a decorator (``@BeautifulOutput(<parameters>)``)
|
|
111
|
+
"""
|
|
112
|
+
self.layout = layout
|
|
113
|
+
self.include_header = include_header
|
|
114
|
+
self.include_footer = include_footer
|
|
115
|
+
self.alternate_footer = alternate_footer
|
|
116
|
+
|
|
117
|
+
# Data
|
|
118
|
+
self._obj_name = ""
|
|
119
|
+
self._signature = ""
|
|
120
|
+
self._result: Any | None = None
|
|
121
|
+
self._performance: PerformanceOutput | None = None
|
|
122
|
+
|
|
123
|
+
# Setting
|
|
124
|
+
self._header_footer_style = "white on blue"
|
|
125
|
+
self._alignment = "center"
|
|
126
|
+
|
|
127
|
+
def __call__(self, obj: Callable[P, R]) -> Callable[P, Group]:
|
|
128
|
+
# Class wrapper
|
|
129
|
+
if isinstance(obj, type):
|
|
130
|
+
raise NotImplementedError("Classes are not supported")
|
|
131
|
+
|
|
132
|
+
# Function wrapper
|
|
133
|
+
@wraps(obj)
|
|
134
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Group:
|
|
135
|
+
"""
|
|
136
|
+
Wrapper function that executes the original function.
|
|
137
|
+
"""
|
|
138
|
+
# Get all parameters inputed
|
|
139
|
+
args_repr = [repr(a) for a in args]
|
|
140
|
+
kwargs_repr = [f"{k}={repr(v)}" for k, v in kwargs.items()]
|
|
141
|
+
self._signature = ", ".join(args_repr + kwargs_repr)
|
|
142
|
+
self._obj_name = obj.__name__
|
|
143
|
+
|
|
144
|
+
# Performance check
|
|
145
|
+
tracemalloc.start() # Start memory measure
|
|
146
|
+
start_time = time.perf_counter() # Start time measure
|
|
147
|
+
|
|
148
|
+
self._result = obj(*args, **kwargs) # Function run
|
|
149
|
+
|
|
150
|
+
finish_time = time.perf_counter() # Get finished time
|
|
151
|
+
_cur, _peak = tracemalloc.get_traced_memory() # Get memory stats
|
|
152
|
+
tracemalloc.stop() # End memory measure
|
|
153
|
+
|
|
154
|
+
self._performance = PerformanceOutput(
|
|
155
|
+
runtime=finish_time - start_time, current_memory=_cur, peak_memory=_peak
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return self._get_layout(layout=self.layout)
|
|
159
|
+
|
|
160
|
+
return wrapper
|
|
161
|
+
|
|
162
|
+
# Signature
|
|
163
|
+
def _func_signature(self) -> str:
|
|
164
|
+
"""Function's signature"""
|
|
165
|
+
return f"{self._obj_name}({self._signature})"
|
|
166
|
+
|
|
167
|
+
# Layout
|
|
168
|
+
def _make_header(self) -> Table:
|
|
169
|
+
header_table = Table.grid(expand=True)
|
|
170
|
+
header_table.add_row(
|
|
171
|
+
Panel(
|
|
172
|
+
Align(f"[b]{self._func_signature()}", align=self._alignment),
|
|
173
|
+
style=self._header_footer_style,
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
return header_table
|
|
177
|
+
|
|
178
|
+
def _make_line(self) -> Table:
|
|
179
|
+
line = Table.grid(expand=True)
|
|
180
|
+
line.add_row(Text("", style=self._header_footer_style))
|
|
181
|
+
return line
|
|
182
|
+
|
|
183
|
+
def _make_footer(self) -> Table:
|
|
184
|
+
if self.alternate_footer:
|
|
185
|
+
return self._make_line()
|
|
186
|
+
|
|
187
|
+
footer_table = Table.grid(expand=True)
|
|
188
|
+
footer_table.add_row(
|
|
189
|
+
Panel(
|
|
190
|
+
Align("[b]BeautifulOutput by absfuyu", align=self._alignment),
|
|
191
|
+
style=self._header_footer_style,
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
return footer_table
|
|
195
|
+
|
|
196
|
+
def _make_result_panel(self) -> Panel:
|
|
197
|
+
result_txt = Text(
|
|
198
|
+
str(self._result),
|
|
199
|
+
overflow="fold",
|
|
200
|
+
no_wrap=False,
|
|
201
|
+
tab_size=2,
|
|
202
|
+
)
|
|
203
|
+
result_panel = Panel(
|
|
204
|
+
Align(result_txt, align=self._alignment),
|
|
205
|
+
title="[bold]Result[/]",
|
|
206
|
+
border_style="green",
|
|
207
|
+
highlight=True,
|
|
208
|
+
)
|
|
209
|
+
return result_panel
|
|
210
|
+
|
|
211
|
+
def _make_performance_panel(self) -> Panel:
|
|
212
|
+
if self._performance is not None:
|
|
213
|
+
performance_panel = Panel(
|
|
214
|
+
Align(self._performance.to_text(), align=self._alignment),
|
|
215
|
+
title="[bold]Performance[/]",
|
|
216
|
+
border_style="red",
|
|
217
|
+
highlight=True,
|
|
218
|
+
# height=result_panel.height,
|
|
219
|
+
)
|
|
220
|
+
return performance_panel
|
|
221
|
+
else:
|
|
222
|
+
return Panel("None", title="[bold]Performance[/]")
|
|
223
|
+
|
|
224
|
+
def _make_output(self) -> Table:
|
|
225
|
+
out_table = Table.grid(expand=True)
|
|
226
|
+
out_table.add_column(ratio=3) # result
|
|
227
|
+
out_table.add_column(ratio=2) # performance
|
|
228
|
+
|
|
229
|
+
out_table.add_row(
|
|
230
|
+
self._make_result_panel(),
|
|
231
|
+
self._make_performance_panel(),
|
|
232
|
+
)
|
|
233
|
+
return out_table
|
|
234
|
+
|
|
235
|
+
def _get_layout(self, layout: int) -> Group:
|
|
236
|
+
header = self._make_header() if self.include_header else Text()
|
|
237
|
+
footer = self._make_footer() if self.include_footer else Text()
|
|
238
|
+
layouts = {
|
|
239
|
+
1: Group(header, self._make_output(), footer),
|
|
240
|
+
2: Group(header, self._make_result_panel(), self._make_performance_panel()),
|
|
241
|
+
3: Group(header, self._make_result_panel(), footer),
|
|
242
|
+
4: Group(self._make_result_panel(), self._make_performance_panel()),
|
|
243
|
+
5: Group(self._make_output()),
|
|
244
|
+
6: Group(
|
|
245
|
+
header,
|
|
246
|
+
self._make_result_panel(),
|
|
247
|
+
self._make_performance_panel(),
|
|
248
|
+
footer,
|
|
249
|
+
),
|
|
250
|
+
}
|
|
251
|
+
return layouts.get(layout, layouts[1])
|
|
@@ -3,12 +3,12 @@ Absfuyu: Data Analysis [W.I.P]
|
|
|
3
3
|
------------------------------
|
|
4
4
|
Extension for ``pd.DataFrame``
|
|
5
5
|
|
|
6
|
-
Version:
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.0.0
|
|
7
|
+
Date updated: 13/02/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
11
|
-
|
|
11
|
+
# ---------------------------------------------------------------------------
|
|
12
12
|
__all__ = [
|
|
13
13
|
# Function
|
|
14
14
|
"compare_2_list",
|
|
@@ -24,60 +24,40 @@ __all__ = [
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
# Library
|
|
27
|
-
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
28
|
import random
|
|
29
29
|
import string
|
|
30
30
|
from collections import deque
|
|
31
31
|
from datetime import datetime
|
|
32
32
|
from itertools import chain, product
|
|
33
|
-
from typing import Any, Literal, NamedTuple, Self
|
|
33
|
+
from typing import Any, ClassVar, Literal, NamedTuple, Self
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
# from scipy import stats
|
|
37
|
-
# from dateutil.relativedelta import relativedelta
|
|
38
|
-
import numpy as np
|
|
39
|
-
import pandas as pd
|
|
40
|
-
from deprecated import deprecated
|
|
41
|
-
from deprecated.sphinx import deprecated as sphinx_deprecated
|
|
42
|
-
from deprecated.sphinx import versionadded
|
|
35
|
+
DA_MODE = False
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
try:
|
|
38
|
+
import numpy as np
|
|
39
|
+
import pandas as pd
|
|
40
|
+
except ImportError:
|
|
41
|
+
from subprocess import run
|
|
46
42
|
|
|
43
|
+
from absfuyu.config import ABSFUYU_CONFIG
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
if ABSFUYU_CONFIG._get_setting("auto-install-extra").value:
|
|
46
|
+
cmd = "python -m pip install -U absfuyu[full]".split()
|
|
47
|
+
run(cmd)
|
|
48
|
+
else:
|
|
49
|
+
raise SystemExit("This feature is in absfuyu[full] package") # noqa: B904
|
|
50
|
+
else:
|
|
51
|
+
DA_MODE = True
|
|
55
52
|
|
|
56
|
-
:param data: np.ndarray | list
|
|
57
|
-
"""
|
|
58
53
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
output = {
|
|
63
|
-
"Observations": len(data),
|
|
64
|
-
"Mean": np.mean(data),
|
|
65
|
-
"Median": np.median(data),
|
|
66
|
-
# "Mode": stats.mode(data)[0][0],
|
|
67
|
-
"Standard deviation": np.std(data),
|
|
68
|
-
"Variance": np.var(data),
|
|
69
|
-
"Max": max(data),
|
|
70
|
-
"Min": min(data),
|
|
71
|
-
"Percentiles": {
|
|
72
|
-
"1st Quartile": np.quantile(data, 0.25),
|
|
73
|
-
"2nd Quartile": np.quantile(data, 0.50),
|
|
74
|
-
"3rd Quartile": np.quantile(data, 0.75),
|
|
75
|
-
# "IQR": stats.iqr(data),
|
|
76
|
-
},
|
|
77
|
-
}
|
|
78
|
-
return output
|
|
54
|
+
from absfuyu.core import ShowAllMethodsMixin, versionadded # noqa: E402
|
|
55
|
+
from absfuyu.logger import logger # noqa: E402
|
|
56
|
+
from absfuyu.util import set_min, set_min_max # noqa: E402
|
|
79
57
|
|
|
80
58
|
|
|
59
|
+
# Function
|
|
60
|
+
# ---------------------------------------------------------------------------
|
|
81
61
|
def equalize_df(data: dict[str, list], fillna=np.nan) -> dict[str, list]:
|
|
82
62
|
"""
|
|
83
63
|
Make all list in dict have equal length to make pd.DataFrame
|
|
@@ -94,9 +74,6 @@ def equalize_df(data: dict[str, list], fillna=np.nan) -> dict[str, list]:
|
|
|
94
74
|
return data
|
|
95
75
|
|
|
96
76
|
|
|
97
|
-
## Update 05/10
|
|
98
|
-
|
|
99
|
-
|
|
100
77
|
def compare_2_list(*arr) -> pd.DataFrame:
|
|
101
78
|
"""
|
|
102
79
|
Compare 2 lists then create DataFrame
|
|
@@ -147,12 +124,6 @@ def rename_with_dict(df: pd.DataFrame, col: str, rename_dict: dict) -> pd.DataFr
|
|
|
147
124
|
:param col: Column name
|
|
148
125
|
:param rename_dict: Rename dictionary
|
|
149
126
|
"""
|
|
150
|
-
# Ver 1.0.1
|
|
151
|
-
# name = f"{col}_filtered"
|
|
152
|
-
# df[name] = df[col]
|
|
153
|
-
# for k, v in rename_dict.items():
|
|
154
|
-
# df[name] = df[name].str.replace(k, v)
|
|
155
|
-
# return df
|
|
156
127
|
|
|
157
128
|
name = f"{col}_filtered"
|
|
158
129
|
df[name] = df[col]
|
|
@@ -162,7 +133,7 @@ def rename_with_dict(df: pd.DataFrame, col: str, rename_dict: dict) -> pd.DataFr
|
|
|
162
133
|
|
|
163
134
|
|
|
164
135
|
# Class
|
|
165
|
-
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
166
137
|
class CityData(NamedTuple):
|
|
167
138
|
"""
|
|
168
139
|
Parameters
|
|
@@ -182,7 +153,7 @@ class CityData(NamedTuple):
|
|
|
182
153
|
area: str
|
|
183
154
|
|
|
184
155
|
@staticmethod
|
|
185
|
-
def _sample_city_data(size: int = 100) -> list
|
|
156
|
+
def _sample_city_data(size: int = 100) -> list:
|
|
186
157
|
"""
|
|
187
158
|
Generate sample city data (testing purpose)
|
|
188
159
|
"""
|
|
@@ -354,7 +325,7 @@ class MatplotlibFormatString:
|
|
|
354
325
|
Format string format: `[marker][line][color]` or `[color][marker][line]`
|
|
355
326
|
"""
|
|
356
327
|
|
|
357
|
-
MARKER_LIST = {
|
|
328
|
+
MARKER_LIST: ClassVar[dict[str, str]] = {
|
|
358
329
|
".": "point marker",
|
|
359
330
|
",": "pixel marker",
|
|
360
331
|
"o": "circle marker",
|
|
@@ -381,13 +352,13 @@ class MatplotlibFormatString:
|
|
|
381
352
|
"|": "vline marker",
|
|
382
353
|
"_": "hline marker",
|
|
383
354
|
}
|
|
384
|
-
LINE_STYLE_LIST = {
|
|
355
|
+
LINE_STYLE_LIST: ClassVar[dict[str, str]] = {
|
|
385
356
|
"-": "solid line style",
|
|
386
357
|
"--": "dashed line style",
|
|
387
358
|
"-.": "dash-dot line style",
|
|
388
359
|
":": "dotted line style",
|
|
389
360
|
}
|
|
390
|
-
COLOR_LIST = {
|
|
361
|
+
COLOR_LIST: ClassVar[dict[str, str]] = {
|
|
391
362
|
"b": "blue",
|
|
392
363
|
"g": "green",
|
|
393
364
|
"r": "red",
|
|
@@ -401,12 +372,12 @@ class MatplotlibFormatString:
|
|
|
401
372
|
LineStyle = _DictToAtrr(LINE_STYLE_LIST, key_as_atrribute=False)
|
|
402
373
|
Color = _DictToAtrr(COLOR_LIST, key_as_atrribute=False)
|
|
403
374
|
|
|
404
|
-
@
|
|
405
|
-
def all_format_string() -> list[PLTFormatString]:
|
|
375
|
+
@classmethod
|
|
376
|
+
def all_format_string(cls) -> list[PLTFormatString]:
|
|
406
377
|
fmt_str = [
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
378
|
+
cls.MARKER_LIST,
|
|
379
|
+
cls.LINE_STYLE_LIST,
|
|
380
|
+
cls.COLOR_LIST,
|
|
410
381
|
]
|
|
411
382
|
return [PLTFormatString._make(x) for x in list(product(*fmt_str))]
|
|
412
383
|
|
|
@@ -420,8 +391,8 @@ class MatplotlibFormatString:
|
|
|
420
391
|
|
|
421
392
|
|
|
422
393
|
# Class - DA
|
|
423
|
-
|
|
424
|
-
class DataAnalystDataFrame(pd.DataFrame):
|
|
394
|
+
# ---------------------------------------------------------------------------
|
|
395
|
+
class DataAnalystDataFrame(ShowAllMethodsMixin, pd.DataFrame):
|
|
425
396
|
"""
|
|
426
397
|
Data Analyst ``pd.DataFrame``
|
|
427
398
|
"""
|
|
@@ -843,13 +814,15 @@ class DataAnalystDataFrame(pd.DataFrame):
|
|
|
843
814
|
# ================================================================
|
|
844
815
|
# Total observation
|
|
845
816
|
@property
|
|
846
|
-
@versionadded(
|
|
817
|
+
@versionadded("3.2.0")
|
|
847
818
|
def total_observation(self) -> int:
|
|
848
|
-
"""
|
|
819
|
+
"""
|
|
820
|
+
Returns total observation of the DataFrame
|
|
821
|
+
"""
|
|
849
822
|
return self.shape[0] * self.shape[1] # type: ignore
|
|
850
823
|
|
|
851
824
|
# Quick info
|
|
852
|
-
@versionadded(
|
|
825
|
+
@versionadded("3.2.0")
|
|
853
826
|
def qinfo(self) -> str:
|
|
854
827
|
"""
|
|
855
828
|
Show quick infomation about DataFrame
|
|
@@ -867,7 +840,7 @@ class DataAnalystDataFrame(pd.DataFrame):
|
|
|
867
840
|
return info
|
|
868
841
|
|
|
869
842
|
# Quick describe
|
|
870
|
-
@versionadded(
|
|
843
|
+
@versionadded("3.2.0")
|
|
871
844
|
def qdescribe(self) -> pd.DataFrame:
|
|
872
845
|
"""
|
|
873
846
|
Quick ``describe()`` that exclude ``object`` and ``datetime`` dtype
|
|
@@ -916,7 +889,7 @@ class DataAnalystDataFrame(pd.DataFrame):
|
|
|
916
889
|
return out
|
|
917
890
|
|
|
918
891
|
# Show distribution
|
|
919
|
-
@versionadded(
|
|
892
|
+
@versionadded("3.2.0")
|
|
920
893
|
def show_distribution(
|
|
921
894
|
self,
|
|
922
895
|
column_name: str,
|
|
@@ -964,6 +937,8 @@ class DataAnalystDataFrame(pd.DataFrame):
|
|
|
964
937
|
6 800 10 10.0
|
|
965
938
|
7 100 9 9.0
|
|
966
939
|
8 500 4 4.0
|
|
940
|
+
|
|
941
|
+
|
|
967
942
|
"""
|
|
968
943
|
out = self[column_name].value_counts(dropna=dropna).to_frame().reset_index()
|
|
969
944
|
if show_percentage:
|
|
@@ -977,12 +952,12 @@ class DataAnalystDataFrame(pd.DataFrame):
|
|
|
977
952
|
return out
|
|
978
953
|
|
|
979
954
|
# Help
|
|
980
|
-
@
|
|
981
|
-
def dadf_help() -> list[str]:
|
|
955
|
+
@classmethod
|
|
956
|
+
def dadf_help(cls) -> list[str]:
|
|
982
957
|
"""
|
|
983
958
|
Show all available method of DataAnalystDataFrame
|
|
984
959
|
"""
|
|
985
|
-
list_of_method = list(set(dir(
|
|
960
|
+
list_of_method = list(set(dir(cls)) - set(dir(pd.DataFrame)))
|
|
986
961
|
return sorted(list_of_method)
|
|
987
962
|
|
|
988
963
|
# Sample DataFrame
|
|
@@ -1066,7 +1041,7 @@ class DADF(DataAnalystDataFrame):
|
|
|
1066
1041
|
class DADF_WIP(DADF):
|
|
1067
1042
|
"""W.I.P"""
|
|
1068
1043
|
|
|
1069
|
-
@versionadded(
|
|
1044
|
+
@versionadded("4.0.0")
|
|
1070
1045
|
def subtract_df(self, other: Self | pd.DataFrame) -> Self:
|
|
1071
1046
|
"""
|
|
1072
1047
|
Subtract DF to find the different rows
|
|
@@ -1079,7 +1054,7 @@ class DADF_WIP(DADF):
|
|
|
1079
1054
|
)
|
|
1080
1055
|
return self.__class__(out)
|
|
1081
1056
|
|
|
1082
|
-
@versionadded(
|
|
1057
|
+
@versionadded("4.0.0")
|
|
1083
1058
|
def merge_left(
|
|
1084
1059
|
self,
|
|
1085
1060
|
other: Self | pd.DataFrame,
|
|
@@ -1092,7 +1067,7 @@ class DADF_WIP(DADF):
|
|
|
1092
1067
|
:param columns: Columns to take from df2
|
|
1093
1068
|
"""
|
|
1094
1069
|
|
|
1095
|
-
if columns:
|
|
1070
|
+
if columns is not None:
|
|
1096
1071
|
current_col = [on]
|
|
1097
1072
|
current_col.extend(columns)
|
|
1098
1073
|
col = other.columns.to_list()
|
|
@@ -1101,9 +1076,3 @@ class DADF_WIP(DADF):
|
|
|
1101
1076
|
|
|
1102
1077
|
out = self.merge(other, how="left", on=on)
|
|
1103
1078
|
return self.__class__(out)
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
# Run
|
|
1107
|
-
###########################################################################
|
|
1108
|
-
if __name__ == "__main__":
|
|
1109
|
-
logger.setLevel(10)
|