mspu 0.0.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.
- mspu-0.0.1/.gitignore +172 -0
- mspu-0.0.1/LICENSE +21 -0
- mspu-0.0.1/PKG-INFO +32 -0
- mspu-0.0.1/README.md +19 -0
- mspu-0.0.1/docs/api/_static/custom.css +22 -0
- mspu-0.0.1/docs/api/_templates/copyright.html +1 -0
- mspu-0.0.1/docs/api/conf.py +111 -0
- mspu-0.0.1/docs/api/data.rst +15 -0
- mspu-0.0.1/docs/api/index.rst +20 -0
- mspu-0.0.1/docs/api/mspu.rst +14 -0
- mspu-0.0.1/docs/api/pandas.rst +18 -0
- mspu-0.0.1/docs/api/polars.rst +20 -0
- mspu-0.0.1/docs/build.sh +19 -0
- mspu-0.0.1/docs/guide/index.md +13 -0
- mspu-0.0.1/docs/guide/tutorial.md +117 -0
- mspu-0.0.1/docs/hooks.py +50 -0
- mspu-0.0.1/docs/mkdocs.yml +167 -0
- mspu-0.0.1/mspu/__init__.py +6 -0
- mspu-0.0.1/mspu/data/__init__.py +5 -0
- mspu-0.0.1/mspu/data/rand_df.py +346 -0
- mspu-0.0.1/mspu/datetime/__init__.py +0 -0
- mspu-0.0.1/mspu/datetime/utils.py +0 -0
- mspu-0.0.1/mspu/io/__init__.py +0 -0
- mspu-0.0.1/mspu/io/file.py +0 -0
- mspu-0.0.1/mspu/pandas/__init__.py +10 -0
- mspu-0.0.1/mspu/pandas/datetime.py +262 -0
- mspu-0.0.1/mspu/pandas/parquet.py +36 -0
- mspu-0.0.1/mspu/pandas/utils.py +196 -0
- mspu-0.0.1/mspu/polars/__init__.py +17 -0
- mspu-0.0.1/mspu/polars/utils.py +142 -0
- mspu-0.0.1/mspu/security/crypt.py +80 -0
- mspu-0.0.1/pyproject.toml +37 -0
- mspu-0.0.1/recipe/meta.yaml +85 -0
- mspu-0.0.1/tests/pandas/test_datetime.py +95 -0
- mspu-0.0.1/tests/pandas/test_parquet.py +12 -0
- mspu-0.0.1/tests/pandas/test_utils.py +82 -0
mspu-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#https://github.com/github/gitignore/blob/main/Python.gitignore
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py,cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
cover/
|
|
55
|
+
|
|
56
|
+
# Translations
|
|
57
|
+
*.mo
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
# Django stuff:
|
|
61
|
+
*.log
|
|
62
|
+
local_settings.py
|
|
63
|
+
db.sqlite3
|
|
64
|
+
db.sqlite3-journal
|
|
65
|
+
|
|
66
|
+
# Flask stuff:
|
|
67
|
+
instance/
|
|
68
|
+
.webassets-cache
|
|
69
|
+
|
|
70
|
+
# Scrapy stuff:
|
|
71
|
+
.scrapy
|
|
72
|
+
|
|
73
|
+
# Sphinx documentation
|
|
74
|
+
docs/_build/
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
.pybuilder/
|
|
78
|
+
target/
|
|
79
|
+
|
|
80
|
+
# Jupyter Notebook
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# IPython
|
|
84
|
+
profile_default/
|
|
85
|
+
ipython_config.py
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
89
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
90
|
+
# .python-version
|
|
91
|
+
|
|
92
|
+
# pipenv
|
|
93
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
94
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
95
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
96
|
+
# install all needed dependencies.
|
|
97
|
+
#Pipfile.lock
|
|
98
|
+
|
|
99
|
+
# poetry
|
|
100
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
101
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
102
|
+
# commonly ignored for libraries.
|
|
103
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
104
|
+
#poetry.lock
|
|
105
|
+
|
|
106
|
+
# pdm
|
|
107
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
108
|
+
#pdm.lock
|
|
109
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
110
|
+
# in version control.
|
|
111
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
112
|
+
.pdm.toml
|
|
113
|
+
|
|
114
|
+
# PEP 582; used by e.g. github.com/user/pyflow and github.com/pdm-project/pdm
|
|
115
|
+
__pypackages__/
|
|
116
|
+
|
|
117
|
+
# Celery stuff
|
|
118
|
+
celerybeat-schedule
|
|
119
|
+
celerybeat.pid
|
|
120
|
+
|
|
121
|
+
# SageMath parsed files
|
|
122
|
+
*.sage.py
|
|
123
|
+
|
|
124
|
+
# Environments
|
|
125
|
+
.env
|
|
126
|
+
.venv
|
|
127
|
+
env/
|
|
128
|
+
venv/
|
|
129
|
+
ENV/
|
|
130
|
+
env.bak/
|
|
131
|
+
venv.bak/
|
|
132
|
+
|
|
133
|
+
# Spyder project settings
|
|
134
|
+
.spyderproject
|
|
135
|
+
.spyproject
|
|
136
|
+
|
|
137
|
+
# Rope project settings
|
|
138
|
+
.ropeproject
|
|
139
|
+
|
|
140
|
+
# build
|
|
141
|
+
/_build
|
|
142
|
+
|
|
143
|
+
# mkdocs documentation
|
|
144
|
+
/site
|
|
145
|
+
|
|
146
|
+
# sphinx documentation
|
|
147
|
+
/docs/api/api
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
Footer
|
|
170
|
+
|
|
171
|
+
# Visual Studio Code settings
|
|
172
|
+
.vscode/
|
mspu-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sean Ma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mspu-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mspu
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Ma's python utils package.
|
|
5
|
+
Author-email: Sean Ma <sean.sl.ma@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: numpy
|
|
10
|
+
Requires-Dist: pandas
|
|
11
|
+
Requires-Dist: polars
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# mspu
|
|
15
|
+
|
|
16
|
+
My python utils package. It includes some commonly used functions, like `gen_rand_df` and `explode_date_range`.
|
|
17
|
+
|
|
18
|
+
## How to install `mspu`
|
|
19
|
+
|
|
20
|
+
Using `pip`:
|
|
21
|
+
```sh
|
|
22
|
+
pip install mspu
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Using `uv`:
|
|
26
|
+
```sh
|
|
27
|
+
uv pip install mspu
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## The document for `mspu`
|
|
31
|
+
|
|
32
|
+
Visit the [document](https://seanslma.github.io/mspu) for more details.
|
mspu-0.0.1/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# mspu
|
|
2
|
+
|
|
3
|
+
My python utils package. It includes some commonly used functions, like `gen_rand_df` and `explode_date_range`.
|
|
4
|
+
|
|
5
|
+
## How to install `mspu`
|
|
6
|
+
|
|
7
|
+
Using `pip`:
|
|
8
|
+
```sh
|
|
9
|
+
pip install mspu
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Using `uv`:
|
|
13
|
+
```sh
|
|
14
|
+
uv pip install mspu
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## The document for `mspu`
|
|
18
|
+
|
|
19
|
+
Visit the [document](https://seanslma.github.io/mspu) for more details.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* Force line break before ALL parameters including the first */
|
|
2
|
+
dt.sig.sig-object em.sig-param::before {
|
|
3
|
+
content: "\A ";
|
|
4
|
+
white-space: pre;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* Ensure commas stay inline */
|
|
8
|
+
dt.sig.sig-object .w {
|
|
9
|
+
display: inline;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* Add comma after last parameter and force line break after it */
|
|
13
|
+
dt.sig.sig-object em.sig-param:last-of-type::after {
|
|
14
|
+
content: ",\A";
|
|
15
|
+
white-space: pre;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Alternative: target the closing parenthesis directly */
|
|
19
|
+
dt.sig.sig-object span.sig-paren:last-of-type::before {
|
|
20
|
+
content: "\A";
|
|
21
|
+
white-space: pre;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{ copyright_html }}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# -- Path setup --------------------------------------------------------------
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
# Add the project root to the path so Sphinx can find the 'mspu' package
|
|
7
|
+
sys.path.insert(0, os.path.abspath('../../'))
|
|
8
|
+
|
|
9
|
+
# -- Project information -----------------------------------------------------
|
|
10
|
+
project = 'mspu'
|
|
11
|
+
copyright = '2026, Sean Ma'
|
|
12
|
+
author = 'Sean Ma'
|
|
13
|
+
release = '0.0.1'
|
|
14
|
+
|
|
15
|
+
# -- General configuration ---------------------------------------------------
|
|
16
|
+
extensions = [
|
|
17
|
+
# Core Sphinx extensions
|
|
18
|
+
'sphinx.ext.autodoc', # To include documentation from docstrings
|
|
19
|
+
'sphinx.ext.viewcode', # To link to the source code
|
|
20
|
+
'sphinx.ext.autosummary', # To automatically generate summary tables
|
|
21
|
+
# Additional utility extensions
|
|
22
|
+
# 'sphinx_autodoc_typehints', # To display type hints nicely
|
|
23
|
+
'numpydoc', # To support NumPy style docstrings
|
|
24
|
+
'sphinx_design', # For badges, cards, etc.
|
|
25
|
+
'sphinx.ext.autodoc',
|
|
26
|
+
'sphinx.ext.napoleon',
|
|
27
|
+
'sphinx_copybutton', # To add copy buttons to code blocks
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# Strip the >>> and ... prompts so copied code is clean
|
|
31
|
+
copybutton_prompt_text = '>>> |\\.\\.\\. '
|
|
32
|
+
copybutton_prompt_is_regexp = True
|
|
33
|
+
|
|
34
|
+
# The suffix(es) of source filenames.
|
|
35
|
+
source_suffix = '.rst'
|
|
36
|
+
|
|
37
|
+
# The master toctree document.
|
|
38
|
+
master_doc = 'index'
|
|
39
|
+
|
|
40
|
+
# Add any paths that contain templates here, relative to this directory.
|
|
41
|
+
templates_path = ['_templates']
|
|
42
|
+
|
|
43
|
+
# List of patterns, relative to source directory, that match files and
|
|
44
|
+
# directories to ignore when looking for source files.
|
|
45
|
+
# This pattern also affects html_static_path and html_extra_path.
|
|
46
|
+
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
|
47
|
+
|
|
48
|
+
# -- Options for HTML output -------------------------------------------------
|
|
49
|
+
# The theme to use. This enables the PyData Sphinx Theme.
|
|
50
|
+
html_theme = 'pydata_sphinx_theme'
|
|
51
|
+
|
|
52
|
+
# The theme options
|
|
53
|
+
html_theme_options = {
|
|
54
|
+
'github_url': 'https://github.com/seanslma/mspu',
|
|
55
|
+
'secondary_sidebar_items': [], # Disable the secondary sidebar items (page toc)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Add any paths that contain custom static files (such as style sheets) here,
|
|
59
|
+
# relative to this directory. They are copied after the builtin static files,
|
|
60
|
+
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
61
|
+
html_static_path = ['_static']
|
|
62
|
+
|
|
63
|
+
# Custom CSS files
|
|
64
|
+
html_css_files = [
|
|
65
|
+
'custom.css',
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# If true, the rest sources are included in the HTML build as _sources/foo.txt.
|
|
69
|
+
html_copy_source = False
|
|
70
|
+
|
|
71
|
+
# disable default copyright
|
|
72
|
+
html_show_copyright = False
|
|
73
|
+
|
|
74
|
+
# Add back to home link and copyright in the footer
|
|
75
|
+
html_context = {
|
|
76
|
+
'copyright_html': f'<a href="/" title="Go to Main Home Page">🏠 Back to Home</a><br>Copyright © {datetime.now().year} Sean Ma'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# If true, "Created using Sphinx" is shown in the HTML footer.
|
|
80
|
+
html_show_sphinx = True
|
|
81
|
+
|
|
82
|
+
# -- Autodoc configuration ---------------------------------------------------
|
|
83
|
+
# Type hints: show in signature only (not in description)
|
|
84
|
+
# autodoc_typehints = "signature"
|
|
85
|
+
|
|
86
|
+
# Use short format for type hints
|
|
87
|
+
# autodoc_typehints_format = "short"
|
|
88
|
+
|
|
89
|
+
# Preserve the defaults in signatures
|
|
90
|
+
autodoc_preserve_defaults = True
|
|
91
|
+
|
|
92
|
+
# -- Sphinx autodoc typehints configuration ----------------------------------
|
|
93
|
+
# This prevents duplicate parameter documentation in the body
|
|
94
|
+
# typehints_defaults = "comma"
|
|
95
|
+
|
|
96
|
+
# -- Numpydoc configuration ---------------------------------------------------
|
|
97
|
+
# Don't show class members automatically
|
|
98
|
+
numpydoc_show_class_members = False
|
|
99
|
+
|
|
100
|
+
# Don't show type hints in the parameter descriptions since they're in signature
|
|
101
|
+
numpydoc_show_type_hint = False
|
|
102
|
+
|
|
103
|
+
# Mock imports for modules that are not available in the documentation environment
|
|
104
|
+
autodoc_mock_imports = []
|
|
105
|
+
|
|
106
|
+
# Global setup for doctests
|
|
107
|
+
doctest_global_setup = """
|
|
108
|
+
import numpy as np
|
|
109
|
+
import polars as pl
|
|
110
|
+
# anything else needed globally
|
|
111
|
+
"""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.. mspu documentation master file
|
|
2
|
+
|
|
3
|
+
mspu API Reference
|
|
4
|
+
==================
|
|
5
|
+
|
|
6
|
+
.. toctree::
|
|
7
|
+
:maxdepth: 2
|
|
8
|
+
:caption: Contents:
|
|
9
|
+
|
|
10
|
+
mspu
|
|
11
|
+
data
|
|
12
|
+
pandas
|
|
13
|
+
polars
|
|
14
|
+
|
|
15
|
+
Indices and tables
|
|
16
|
+
==================
|
|
17
|
+
|
|
18
|
+
* :ref:`genindex`
|
|
19
|
+
* :ref:`modindex`
|
|
20
|
+
* :ref:`search`
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.. _api.polars:
|
|
2
|
+
|
|
3
|
+
polars
|
|
4
|
+
======
|
|
5
|
+
|
|
6
|
+
.. currentmodule:: mspu.polars
|
|
7
|
+
|
|
8
|
+
Functions
|
|
9
|
+
~~~~~~~~~
|
|
10
|
+
|
|
11
|
+
.. autosummary::
|
|
12
|
+
:toctree: api/
|
|
13
|
+
:nosignatures:
|
|
14
|
+
|
|
15
|
+
pl_ht
|
|
16
|
+
inf_count
|
|
17
|
+
nan_count
|
|
18
|
+
nul_count
|
|
19
|
+
lowercase_polars_df
|
|
20
|
+
to_float32_polars_df
|
mspu-0.0.1/docs/build.sh
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Step 1: Clean any old builds
|
|
4
|
+
rm -rf _build/html/
|
|
5
|
+
|
|
6
|
+
# Step 2: Change to the docs directory
|
|
7
|
+
cd docs
|
|
8
|
+
|
|
9
|
+
# Step 3: Build the MkDocs guide first (creates the '_build/html' folder)
|
|
10
|
+
mkdocs build --site-dir ../_build/html
|
|
11
|
+
|
|
12
|
+
# Step 4: Build Sphinx directly into the compiled MkDocs '_build/api' folder
|
|
13
|
+
sphinx-build -b html api ../_build/html/api
|
|
14
|
+
|
|
15
|
+
# Step 5: Return to the root directory
|
|
16
|
+
cd ..
|
|
17
|
+
|
|
18
|
+
# Copy to the final build directory
|
|
19
|
+
cp -a ./_build/html/. ../seanslma.github.io/mspu/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Welcome to mspu
|
|
2
|
+
|
|
3
|
+
mspu is a Python package designed for providing some commonly used functions.
|
|
4
|
+
|
|
5
|
+
This user guide is intended to walk you through getting started, providing examples, and explaining core concepts.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
User Guide (You Are Here): Conceptual overviews, installation steps, and tutorials.
|
|
10
|
+
|
|
11
|
+
API Reference (External Link): Detailed, auto-generated documentation for every function and class (powered by Sphinx).
|
|
12
|
+
|
|
13
|
+
Check out the Tutorial to see how mspu works!
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Quick Tutorial: Using explode_date_range
|
|
2
|
+
|
|
3
|
+
This tutorial shows you how to use the `mspu.pandas.explode_date_range` function.
|
|
4
|
+
|
|
5
|
+
## 1. Install the package
|
|
6
|
+
|
|
7
|
+
First, ensure you have the `mspu` package installed:
|
|
8
|
+
```sh
|
|
9
|
+
pip install mspu
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 2. Displaying dataframe
|
|
13
|
+
|
|
14
|
+
When you print a pandas DataFrame, sometimes the default settings are not good enough so you need to adjust the display width, number of rows and columns. Here we provide a simple function for your convinence.
|
|
15
|
+
|
|
16
|
+
```py
|
|
17
|
+
import pandas as pd
|
|
18
|
+
from mspu.pandas import pd_ht
|
|
19
|
+
pd.DataFrame.ht = pd_ht
|
|
20
|
+
df = pd.DataFrame({
|
|
21
|
+
'foo': [1.12345, 2.98765, 3.14159],
|
|
22
|
+
'bar': [7, 8, 9],
|
|
23
|
+
'ham': ['x', 'y', 'z'],
|
|
24
|
+
})
|
|
25
|
+
df.ht(n=1, c=2, r=3)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The output:
|
|
29
|
+
```
|
|
30
|
+
shape: (3, 3)
|
|
31
|
+
foo ... ham
|
|
32
|
+
0 1.123 ... x
|
|
33
|
+
2 3.142 ... z
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 3. Creating random data
|
|
37
|
+
|
|
38
|
+
The `gen_rand_df` can be used to create random data in a pandas DataFrame for testing.
|
|
39
|
+
|
|
40
|
+
In this example, we'll create a dataframe with one string column, two timestamp columns, one integer column, and two float columns, for one year with a resolution of one minute.
|
|
41
|
+
|
|
42
|
+
```py
|
|
43
|
+
from mspu.data import gen_rand_df
|
|
44
|
+
|
|
45
|
+
df = gen_rand_df(
|
|
46
|
+
nrow=100,
|
|
47
|
+
str_cols=1,
|
|
48
|
+
ts_cols={
|
|
49
|
+
'count': 2,
|
|
50
|
+
'name': ['start_date', 'end_date'],
|
|
51
|
+
'start_date': ['2020-01-01', '2023-01-01'],
|
|
52
|
+
'end_date': ['2023-01-01', '2025-01-01'],
|
|
53
|
+
'freq': 'MS',
|
|
54
|
+
'random': True,
|
|
55
|
+
},
|
|
56
|
+
int_cols=1,
|
|
57
|
+
float_cols=2,
|
|
58
|
+
)
|
|
59
|
+
df.ht(1, c=-1, r=2)
|
|
60
|
+
```
|
|
61
|
+
Outputs:
|
|
62
|
+
```
|
|
63
|
+
shape: (100, 6)
|
|
64
|
+
s1 start_date end_date i1 f1 f2
|
|
65
|
+
0 IZD8v 2022-10-01 2023-12-01 0 1.43 1.78
|
|
66
|
+
99 y5HeH 2020-12-01 2024-07-01 0 1.13 1.11
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 4. Using the `explode_date_range` function
|
|
71
|
+
|
|
72
|
+
This function can be used to explode two datetime columns in a pandas DataFrame to a list of datetime values as a new column. It's about `30x` faster than using the pandas `df.explode` function.
|
|
73
|
+
```py
|
|
74
|
+
import time
|
|
75
|
+
from mspu.pandas import explode_date_range
|
|
76
|
+
|
|
77
|
+
# assume we already created the df in the previous section
|
|
78
|
+
t0 = time.time()
|
|
79
|
+
df_exploded = explode_date_range(
|
|
80
|
+
df=df,
|
|
81
|
+
start_date_col='start_date',
|
|
82
|
+
end_date_col='end_date',
|
|
83
|
+
date_col='ts',
|
|
84
|
+
freq='30min',
|
|
85
|
+
inclusive='left',
|
|
86
|
+
drop_date_cols=True,
|
|
87
|
+
)
|
|
88
|
+
print(f'mspu explode time: {time.time() - t0:.3f} seconds')
|
|
89
|
+
df_exploded.ht(2,r=2)
|
|
90
|
+
```
|
|
91
|
+
Outputs:
|
|
92
|
+
```
|
|
93
|
+
mspu explode time: 0.235 seconds
|
|
94
|
+
shape: (4415424, 5)
|
|
95
|
+
s1 i1 f1 f2 ts
|
|
96
|
+
0 IZD8v 0 1.43 1.78 2022-10-01 00:00:00
|
|
97
|
+
1 IZD8v 0 1.43 1.78 2022-10-01 00:30:00
|
|
98
|
+
4415422 y5HeH 0 1.13 1.11 2024-06-30 23:00:00
|
|
99
|
+
4415423 y5HeH 0 1.13 1.11 2024-06-30 23:30:00
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Now let's use `explode` from pandas:
|
|
103
|
+
```py
|
|
104
|
+
t1 = time.time()
|
|
105
|
+
df['ts'] = [
|
|
106
|
+
pd.date_range(start, end, freq='30min', inclusive='left')
|
|
107
|
+
for start, end in zip(df['start_date'].values, df['end_date'].values)
|
|
108
|
+
]
|
|
109
|
+
df_exploded_pandas = df.drop(columns=['start_date', 'end_date']).explode('ts')
|
|
110
|
+
print(f'pandas explode time: {time.time() - t1:.3f} seconds')
|
|
111
|
+
print(df_exploded.equals(df_exploded_pandas.reset_index(drop=True)))
|
|
112
|
+
```
|
|
113
|
+
Outputs:
|
|
114
|
+
```
|
|
115
|
+
pandas explode time: 4.117 seconds
|
|
116
|
+
True
|
|
117
|
+
```
|
mspu-0.0.1/docs/hooks.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import datetime
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def on_page_markdown(markdown, **kwargs):
|
|
6
|
+
"""
|
|
7
|
+
Add blank line before lists that don't have one.
|
|
8
|
+
Matches: text\n- item (no blank line)
|
|
9
|
+
Replaces with: text\n\n- item (adds blank line)
|
|
10
|
+
"""
|
|
11
|
+
# Pattern: non-empty line followed by newline and list item
|
|
12
|
+
# Negative lookbehind ensures previous line isn't already blank
|
|
13
|
+
pattern = r'(?<!\n)\n([-*+]\s)'
|
|
14
|
+
replacement = r'\n\n\1'
|
|
15
|
+
|
|
16
|
+
return re.sub(pattern, replacement, markdown)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def on_config(config):
|
|
20
|
+
# Replace {year} once globally
|
|
21
|
+
now = datetime.datetime.now()
|
|
22
|
+
# date = now.strftime('%-d %b %Y')
|
|
23
|
+
copyright = config.get('copyright', '')
|
|
24
|
+
config['raw_copyright'] = copyright.replace('{year}', str(now.year))
|
|
25
|
+
|
|
26
|
+
return config
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def on_page_context(context, page, config, nav):
|
|
30
|
+
# Determine which date to use
|
|
31
|
+
if page.is_homepage:
|
|
32
|
+
display_date = datetime.datetime.now().strftime('%-d %b %Y')
|
|
33
|
+
else:
|
|
34
|
+
# Try to get the Git date from plugin metadata
|
|
35
|
+
display_date = (
|
|
36
|
+
page.meta.get('git_revision_date_localized')
|
|
37
|
+
or page.meta.get('revision_date')
|
|
38
|
+
or datetime.datetime.now().strftime('%-d %b %Y')
|
|
39
|
+
)
|
|
40
|
+
updated_at = f'Last updated on {display_date}'
|
|
41
|
+
|
|
42
|
+
# Remove it from metadata to avoid auto creating `last updated` field
|
|
43
|
+
page.meta.pop('git_revision_date_localized', None)
|
|
44
|
+
|
|
45
|
+
# Build a per-page footer WITHOUT mutating the global config
|
|
46
|
+
# Use context['copyright'] instead of config['copyright']
|
|
47
|
+
copyright = config['raw_copyright']
|
|
48
|
+
context['config']['copyright'] = f'{copyright}<br>{updated_at}'
|
|
49
|
+
|
|
50
|
+
return context
|