pandas-plots 0.9.6__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.
@@ -0,0 +1,7 @@
1
+ Copyright 2024 smeisegeier
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,154 @@
1
+ Metadata-Version: 2.1
2
+ Name: pandas-plots
3
+ Version: 0.9.6
4
+ Summary: A collection of helper for table handling and vizualization
5
+ Home-page: https://github.com/smeisegeier/pandas-plots
6
+ Author: smeisegeier
7
+ Author-email: dexterDSDo@googlemail.com
8
+ License: MIT License
9
+ Project-URL: Documentation, https://github.com/smeisegeier/pandas-plots
10
+ Project-URL: Source Code, https://github.com/smeisegeier/pandas-plots
11
+ Project-URL: Bug Tracker, https://github.com/smeisegeier/pandas-plots/issues
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: pandas>=2.0.0
23
+ Requires-Dist: plotly>=5.18.0
24
+ Requires-Dist: matplotlib>=3.8.2
25
+ Requires-Dist: matplotlib-venn>=0.11.10
26
+ Requires-Dist: seaborn>=0.13.2
27
+ Requires-Dist: Jinja2>=3.1.3
28
+ Requires-Dist: requests>=2.31.0
29
+
30
+ # pandas-plots
31
+
32
+ ![PyPI - Version](https://img.shields.io/pypi/v/pandas-plots) ![GitHub last commit](https://img.shields.io/github/last-commit/smeisegeier/pandas-plots?logo=github) ![GitHub License](https://img.shields.io/github/license/smeisegeier/pandas-plots?logo=github) ![py3.10](https://img.shields.io/badge/python-3.10-blue.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICA8ZGVmcz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0icHlZZWxsb3ciIGdyYWRpZW50VHJhbnNmb3JtPSJyb3RhdGUoNDUpIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI2ZlNSIgb2Zmc2V0PSIwLjYiLz4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI2RhMSIgb2Zmc2V0PSIxIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJweUJsdWUiIGdyYWRpZW50VHJhbnNmb3JtPSJyb3RhdGUoNDUpIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzY5ZiIgb2Zmc2V0PSIwLjQiLz4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzQ2OCIgb2Zmc2V0PSIxIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KCiAgPHBhdGggZD0iTTI3LDE2YzAtNyw5LTEzLDI0LTEzYzE1LDAsMjMsNiwyMywxM2wwLDIyYzAsNy01LDEyLTExLDEybC0yNCwwYy04LDAtMTQsNi0xNCwxNWwwLDEwbC05LDBjLTgsMC0xMy05LTEzLTI0YzAtMTQsNS0yMywxMy0yM2wzNSwwbDAtM2wtMjQsMGwwLTlsMCwweiBNODgsNTB2MSIgZmlsbD0idXJsKCNweUJsdWUpIi8+CiAgPHBhdGggZD0iTTc0LDg3YzAsNy04LDEzLTIzLDEzYy0xNSwwLTI0LTYtMjQtMTNsMC0yMmMwLTcsNi0xMiwxMi0xMmwyNCwwYzgsMCwxNC03LDE0LTE1bDAtMTBsOSwwYzcsMCwxMyw5LDEzLDIzYzAsMTUtNiwyNC0xMywyNGwtMzUsMGwwLDNsMjMsMGwwLDlsMCwweiBNMTQwLDUwdjEiIGZpbGw9InVybCgjcHlZZWxsb3cpIi8+CgogIDxjaXJjbGUgcj0iNCIgY3g9IjY0IiBjeT0iODgiIGZpbGw9IiNGRkYiLz4KICA8Y2lyY2xlIHI9IjQiIGN4PSIzNyIgY3k9IjE1IiBmaWxsPSIjRkZGIi8+Cjwvc3ZnPgo=)
33
+
34
+ ## usage
35
+
36
+ install / update package
37
+
38
+ ```bash
39
+ pip install pandas-plots -U
40
+ ```
41
+
42
+ include in python
43
+
44
+ ```python
45
+ from pandas_plots import tbl, pls, ven, hlp
46
+ ```
47
+
48
+ ## example
49
+
50
+ ```python
51
+ # load sample dataset from seaborn
52
+ import seaborn as sb
53
+ df = sb.load_dataset('taxis')
54
+ ```
55
+
56
+ ```python
57
+ _df = df[["passengers", "distance", "fare"]][:5]
58
+ tbl.show_num_df(
59
+ _df,
60
+ total_axis="xy",
61
+ total_mode="mean",
62
+ data_bar_axis="xy",
63
+ pct_axis="xy",
64
+ precision=0,
65
+ kpi_mode="max_min_x",
66
+ kpi_rag_list=(1,7),
67
+ )
68
+ ```
69
+
70
+ ![show_num](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-03-02-17-33-43.png?raw=true)
71
+
72
+ ## why use pandas-plots
73
+
74
+ `pandas-plots` is a package to help you examine and visualize data that are organized in a pandas DataFrame. It provides a high level api to pandas / plotly with some selected functions.
75
+
76
+ It is subdivided into:
77
+
78
+ - `tbl` utilities for table descriptions
79
+ - 🌟`show_num_df()` displays a table as styled version with additional information
80
+ - `describe_df()` an alternative version of pandas `describe()` function
81
+ - `pivot_df()` gets a pivot table of a 3 column dataframe
82
+ - _⚠️ `pivot_df()` is depricated and wont get further updates. Its features are well covered in standard `pd.pivot_table()`_
83
+
84
+ - `pls` for plotly visualizations
85
+ - `plot_box()` auto annotated boxplot w/ violin option
86
+ - `plot_boxes()` multiple boxplots _(annotation is experimental)_
87
+ - `plots_bars()` a standardized bar plot
88
+ - 🆕 now features convidence intervals via `use_ci` option
89
+ - `plot_stacked_bars()` shortcut to stacked bars 😄
90
+ - `plot_quadrants()` quickly shows a 2x2 heatmap
91
+
92
+ - `ven` offers functions for _venn diagrams_
93
+ - `show_venn2()` displays a venn diagram for 2 sets
94
+ - `show_venn3()` displays a venn diagram for 3 sets
95
+
96
+ - `hlp` contains some (variety) helper functions
97
+ - `df_to_series()` converts a dataframe to a series
98
+ - `mean_confidence_interval()` calculates mean and confidence interval for a series
99
+ - `wrap_text()` formats strings or lists to a given width to fit nicely on the screen
100
+ - `replace_delimiter_outside_quotes()` when manual import of csv files is needed: replaces delimiters only outside of quotes
101
+
102
+ > note: theme setting can be controlled through all functions by setting the environment variable `THEME` to either light or dark
103
+
104
+ ## more examples
105
+
106
+ ```python
107
+ pls.plot_box(df['fare'], height=400, violin=True)
108
+ ```
109
+
110
+ ![plot_box](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-13-00-40-27.png?raw=true)
111
+
112
+ ```python
113
+ # quick and exhaustive description of any table
114
+ tbl.describe_df(df, 'taxis', top_n_uniques=5)
115
+ ```
116
+
117
+ ![describe_df](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-14-20-49-00.png?raw=true)
118
+
119
+ ```python
120
+ # show bars with confidence intervals
121
+ _df = df[["payment", "fare"]]
122
+ pls.plot_bars(
123
+ _df,
124
+ dropna=False,
125
+ use_ci=True,
126
+ height=600,
127
+ width=800,
128
+ precision=1,
129
+ )
130
+ ```
131
+
132
+ ![bars_with_ci](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-03-24-09-59-32.png?raw=true)
133
+
134
+ ```python
135
+ # show venn diagram for 3 sets
136
+ from pandas_plots import ven
137
+
138
+ set_a = {'ford','ferrari','mercedes', 'bmw'}
139
+ set_b = {'opel','bmw','bentley','audi'}
140
+ set_c = {'ferrari','bmw','chrysler','renault','peugeot','fiat'}
141
+ _df, _details = ven.show_venn3(
142
+ title="taxis",
143
+ a_set=set_a,
144
+ a_label="cars1",
145
+ b_set=set_b,
146
+ b_label="cars2",
147
+ c_set=set_c,
148
+ c_label="cars3",
149
+ verbose=0,
150
+ size=8,
151
+ )
152
+ ```
153
+
154
+ ![venn](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-19-20-49-52.png?raw=true)
@@ -0,0 +1,125 @@
1
+ # pandas-plots
2
+
3
+ ![PyPI - Version](https://img.shields.io/pypi/v/pandas-plots) ![GitHub last commit](https://img.shields.io/github/last-commit/smeisegeier/pandas-plots?logo=github) ![GitHub License](https://img.shields.io/github/license/smeisegeier/pandas-plots?logo=github) ![py3.10](https://img.shields.io/badge/python-3.10-blue.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICA8ZGVmcz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0icHlZZWxsb3ciIGdyYWRpZW50VHJhbnNmb3JtPSJyb3RhdGUoNDUpIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI2ZlNSIgb2Zmc2V0PSIwLjYiLz4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI2RhMSIgb2Zmc2V0PSIxIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJweUJsdWUiIGdyYWRpZW50VHJhbnNmb3JtPSJyb3RhdGUoNDUpIj4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzY5ZiIgb2Zmc2V0PSIwLjQiLz4KICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iIzQ2OCIgb2Zmc2V0PSIxIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KCiAgPHBhdGggZD0iTTI3LDE2YzAtNyw5LTEzLDI0LTEzYzE1LDAsMjMsNiwyMywxM2wwLDIyYzAsNy01LDEyLTExLDEybC0yNCwwYy04LDAtMTQsNi0xNCwxNWwwLDEwbC05LDBjLTgsMC0xMy05LTEzLTI0YzAtMTQsNS0yMywxMy0yM2wzNSwwbDAtM2wtMjQsMGwwLTlsMCwweiBNODgsNTB2MSIgZmlsbD0idXJsKCNweUJsdWUpIi8+CiAgPHBhdGggZD0iTTc0LDg3YzAsNy04LDEzLTIzLDEzYy0xNSwwLTI0LTYtMjQtMTNsMC0yMmMwLTcsNi0xMiwxMi0xMmwyNCwwYzgsMCwxNC03LDE0LTE1bDAtMTBsOSwwYzcsMCwxMyw5LDEzLDIzYzAsMTUtNiwyNC0xMywyNGwtMzUsMGwwLDNsMjMsMGwwLDlsMCwweiBNMTQwLDUwdjEiIGZpbGw9InVybCgjcHlZZWxsb3cpIi8+CgogIDxjaXJjbGUgcj0iNCIgY3g9IjY0IiBjeT0iODgiIGZpbGw9IiNGRkYiLz4KICA8Y2lyY2xlIHI9IjQiIGN4PSIzNyIgY3k9IjE1IiBmaWxsPSIjRkZGIi8+Cjwvc3ZnPgo=)
4
+
5
+ ## usage
6
+
7
+ install / update package
8
+
9
+ ```bash
10
+ pip install pandas-plots -U
11
+ ```
12
+
13
+ include in python
14
+
15
+ ```python
16
+ from pandas_plots import tbl, pls, ven, hlp
17
+ ```
18
+
19
+ ## example
20
+
21
+ ```python
22
+ # load sample dataset from seaborn
23
+ import seaborn as sb
24
+ df = sb.load_dataset('taxis')
25
+ ```
26
+
27
+ ```python
28
+ _df = df[["passengers", "distance", "fare"]][:5]
29
+ tbl.show_num_df(
30
+ _df,
31
+ total_axis="xy",
32
+ total_mode="mean",
33
+ data_bar_axis="xy",
34
+ pct_axis="xy",
35
+ precision=0,
36
+ kpi_mode="max_min_x",
37
+ kpi_rag_list=(1,7),
38
+ )
39
+ ```
40
+
41
+ ![show_num](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-03-02-17-33-43.png?raw=true)
42
+
43
+ ## why use pandas-plots
44
+
45
+ `pandas-plots` is a package to help you examine and visualize data that are organized in a pandas DataFrame. It provides a high level api to pandas / plotly with some selected functions.
46
+
47
+ It is subdivided into:
48
+
49
+ - `tbl` utilities for table descriptions
50
+ - 🌟`show_num_df()` displays a table as styled version with additional information
51
+ - `describe_df()` an alternative version of pandas `describe()` function
52
+ - `pivot_df()` gets a pivot table of a 3 column dataframe
53
+ - _⚠️ `pivot_df()` is depricated and wont get further updates. Its features are well covered in standard `pd.pivot_table()`_
54
+
55
+ - `pls` for plotly visualizations
56
+ - `plot_box()` auto annotated boxplot w/ violin option
57
+ - `plot_boxes()` multiple boxplots _(annotation is experimental)_
58
+ - `plots_bars()` a standardized bar plot
59
+ - 🆕 now features convidence intervals via `use_ci` option
60
+ - `plot_stacked_bars()` shortcut to stacked bars 😄
61
+ - `plot_quadrants()` quickly shows a 2x2 heatmap
62
+
63
+ - `ven` offers functions for _venn diagrams_
64
+ - `show_venn2()` displays a venn diagram for 2 sets
65
+ - `show_venn3()` displays a venn diagram for 3 sets
66
+
67
+ - `hlp` contains some (variety) helper functions
68
+ - `df_to_series()` converts a dataframe to a series
69
+ - `mean_confidence_interval()` calculates mean and confidence interval for a series
70
+ - `wrap_text()` formats strings or lists to a given width to fit nicely on the screen
71
+ - `replace_delimiter_outside_quotes()` when manual import of csv files is needed: replaces delimiters only outside of quotes
72
+
73
+ > note: theme setting can be controlled through all functions by setting the environment variable `THEME` to either light or dark
74
+
75
+ ## more examples
76
+
77
+ ```python
78
+ pls.plot_box(df['fare'], height=400, violin=True)
79
+ ```
80
+
81
+ ![plot_box](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-13-00-40-27.png?raw=true)
82
+
83
+ ```python
84
+ # quick and exhaustive description of any table
85
+ tbl.describe_df(df, 'taxis', top_n_uniques=5)
86
+ ```
87
+
88
+ ![describe_df](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-14-20-49-00.png?raw=true)
89
+
90
+ ```python
91
+ # show bars with confidence intervals
92
+ _df = df[["payment", "fare"]]
93
+ pls.plot_bars(
94
+ _df,
95
+ dropna=False,
96
+ use_ci=True,
97
+ height=600,
98
+ width=800,
99
+ precision=1,
100
+ )
101
+ ```
102
+
103
+ ![bars_with_ci](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-03-24-09-59-32.png?raw=true)
104
+
105
+ ```python
106
+ # show venn diagram for 3 sets
107
+ from pandas_plots import ven
108
+
109
+ set_a = {'ford','ferrari','mercedes', 'bmw'}
110
+ set_b = {'opel','bmw','bentley','audi'}
111
+ set_c = {'ferrari','bmw','chrysler','renault','peugeot','fiat'}
112
+ _df, _details = ven.show_venn3(
113
+ title="taxis",
114
+ a_set=set_a,
115
+ a_label="cars1",
116
+ b_set=set_b,
117
+ b_label="cars2",
118
+ c_set=set_c,
119
+ c_label="cars3",
120
+ verbose=0,
121
+ size=8,
122
+ )
123
+ ```
124
+
125
+ ![venn](https://github.com/smeisegeier/pandas-plots/blob/main/img/2024-02-19-20-49-52.png?raw=true)
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ # [project]
6
+ # name = "pandas-plots"
7
+ # version = "0.8.2"
8
+ # requires-python = ">=3.10"
9
+ # description = "A collection of helper for table handling and vizualization"
10
+ # readme = "README.md"
11
+ # authors = [{ name = "smeisegeier", email = "dexterDSDo@googlemail.com" }]
12
+ # license = { text = "MIT licence" }
13
+ # # license = { file = "LICENSE" }
14
+ # classifiers = [
15
+ # "License :: OSI Approved :: MIT License",
16
+ # "Programming Language :: Python :: 3",
17
+ # "Programming Language :: Python :: 3.10",
18
+ # 'Development Status :: 4 - Beta',
19
+ # 'Intended Audience :: Science/Research',
20
+ # 'Operating System :: OS Independent',
21
+ # 'Topic :: Scientific/Engineering'
22
+ # ]
23
+ # keywords = ["tables", "pivot", "plotly", "venn", "plot", "vizualization"]
24
+ # dependencies = [
25
+ # "pandas >= 2.0.0",
26
+ # "plotly >= 5.18.0",
27
+ # "matplotlib >= 3.8.2",
28
+ # "matplotlib-venn >= 0.11.10",
29
+ # "seaborn >= 0.13.2",
30
+ # "sqlalchemy < 2.0.0",
31
+ # "Jinja2 >= 3.1.3",
32
+ # ]
33
+
34
+ # # [project.optional-dependencies]
35
+ # # dev = ["black", "bumpver", "isort", "pip-tools", "pytest"]
36
+
37
+ # [project.urls]
38
+ # homepage = "https://github.com/smeisegeier/pandas-plots"
39
+ # repository = "https://github.com/smeisegeier/pandas-plots"
40
+
41
+ # # [project.scripts]
42
+ # # realpython = "reader.__main__:main"
@@ -0,0 +1,39 @@
1
+ [metadata]
2
+ name = pandas-plots
3
+ version = 0.9.6
4
+ author = smeisegeier
5
+ author_email = dexterDSDo@googlemail.com
6
+ description = A collection of helper for table handling and vizualization
7
+ long_description = file: README.md
8
+ long_description_content_type = text/markdown
9
+ license = MIT License
10
+ license_files = LICENSE
11
+ url = https://github.com/smeisegeier/pandas-plots
12
+ project_urls =
13
+ Documentation = https://github.com/smeisegeier/pandas-plots
14
+ Source Code = https://github.com/smeisegeier/pandas-plots
15
+ Bug Tracker = https://github.com/smeisegeier/pandas-plots/issues
16
+ classifiers =
17
+ License :: OSI Approved :: MIT License
18
+ Programming Language :: Python :: 3
19
+ Programming Language :: Python :: 3.10
20
+ Development Status :: 4 - Beta
21
+ Intended Audience :: Science/Research
22
+ Operating System :: OS Independent
23
+ Topic :: Scientific/Engineering
24
+
25
+ [options]
26
+ python_requires = >=3.10
27
+ install_requires =
28
+ pandas >= 2.0.0
29
+ plotly >= 5.18.0
30
+ matplotlib >= 3.8.2
31
+ matplotlib-venn >= 0.11.10
32
+ seaborn >= 0.13.2
33
+ Jinja2 >= 3.1.3
34
+ requests >= 2.31.0
35
+
36
+ [egg_info]
37
+ tag_build =
38
+ tag_date = 0
39
+
@@ -0,0 +1,204 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import scipy.stats
4
+
5
+ from io import BytesIO
6
+ from matplotlib import pyplot as plt
7
+ from PIL import Image
8
+ import requests
9
+ import re
10
+
11
+ from tenacity import retry
12
+
13
+ URL_REGEX = r"^(?:http|ftp)s?://" # https://stackoverflow.com/a/1617386
14
+
15
+
16
+ def mean_confidence_interval(df, confidence=0.95):
17
+ """
18
+ Calculate the mean and confidence interval of the input dataframe.
19
+ source: https://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data
20
+
21
+ Parameters:
22
+ df (array-like): The input dataframe.
23
+ confidence (float, optional): The confidence level for the interval. Defaults to 0.95.
24
+
25
+ Returns:
26
+ tuple: A tuple containing the mean, interval, lower bound, and upper bound.
27
+ """
28
+ df = df_to_series(df)
29
+ if df is None:
30
+ return None
31
+ a = 1.0 * np.array(df)
32
+ n = len(a)
33
+ mean, se = np.mean(a), scipy.stats.sem(a)
34
+ # * calculate the margin of error for the confidence interval using the t-distribution with the specified confidence level.
35
+ margin = se * scipy.stats.t.ppf((1 + confidence) / 2.0, n - 1)
36
+ lower = mean - margin
37
+ upper = mean + margin
38
+ return mean, margin, lower, upper
39
+
40
+ # # * Alternative
41
+ # # from statistics import NormalDist
42
+ # def confidence_interval(data, confidence=0.95):
43
+ # dist = NormalDist.from_samples(data)
44
+ # z = NormalDist().inv_cdf((1 + confidence) / 2.)
45
+ # h = dist.stdev * z / ((len(data) - 1) ** .5)
46
+ # return dist.mean - h, dist.mean + h
47
+
48
+
49
+ def df_to_series(df) -> pd.Series | None:
50
+ """
51
+ Converts a pandas DataFrame to a pandas Series.
52
+
53
+ Parameters:
54
+ df (pd.DataFrame): The DataFrame to be converted.
55
+
56
+ Returns:
57
+ pd.Series | None: The converted Series if successful, None otherwise.
58
+
59
+ Raises:
60
+ None
61
+
62
+ Notes:
63
+ - If the input `df` is already a Series, it is returned as is.
64
+ - If the input `df` has more than 2 columns, an error message is printed and None is returned.
65
+ - If the input `df` has 1 column, a new Series is created with the input column as the data and the input index as the index.
66
+ - If the input `df` has 2 columns, the function checks which column is the index. If the first column is numeric, the second column is set as the data and the first column is set as the index. If the second column is numeric, the first column is set as the data and the second column is set as the index. If neither column is numeric, an error message is printed and None is returned.
67
+ - The index and name of the resulting Series are set to the appropriate labels.
68
+ """
69
+ # * check if df is a series
70
+ if isinstance(df, pd.Series):
71
+ return df
72
+ # * too many columns
73
+ if len(df.columns) > 2:
74
+ print("❌ df must have exactly 2 columns")
75
+ return None
76
+ # * df can have 1 column, proper index is assumed then
77
+ elif len(df.columns) == 1:
78
+ return pd.Series(index=df.index, data=df.iloc[:, 0].values, name=df.columns[0])
79
+ else:
80
+ # * check which column is the index
81
+ if pd.api.types.is_numeric_dtype(df.iloc[:, 0]):
82
+ _idx_col = df.iloc[:, 1]
83
+ _data_col = df.iloc[:, 0]
84
+ elif pd.api.types.is_numeric_dtype(df.iloc[:, 1]):
85
+ _idx_col = df.iloc[:, 0]
86
+ _data_col = df.iloc[:, 1]
87
+ else:
88
+ print("❌ df must have exactly 1 numeric column")
89
+ return None
90
+ s = pd.Series(
91
+ index=_idx_col.values,
92
+ data=_data_col.values,
93
+ )
94
+ # * set index and name to proper labels
95
+ s.index.name = _idx_col.name
96
+ s.name = _data_col.name
97
+ return s
98
+
99
+
100
+ def replace_delimiter_outside_quotes(
101
+ input: str, delimiter_old: str = ",", delimiter_new: str = ";", quotechar: str = '"'
102
+ ):
103
+ """
104
+ Replace the old delimiter with the new delimiter outside of quotes in the input string.
105
+
106
+ Args:
107
+ input (str): The input string
108
+ delimiter_old (str): The old delimiter to be replaced
109
+ delimiter_new (str): The new delimiter to replace the old delimiter
110
+ quotechar (str): The character used to denote quotes
111
+
112
+ Returns:
113
+ str: The modified string with the delimiters replaced
114
+ """
115
+ outside_quotes = True
116
+ output = ""
117
+ # * loop through input and toggle inside/outside status
118
+ for char in input:
119
+ if char == quotechar:
120
+ outside_quotes = not outside_quotes
121
+ elif outside_quotes and char == delimiter_old:
122
+ char = delimiter_new
123
+ output += char
124
+ return output
125
+
126
+
127
+ def wrap_text(
128
+ text: str | list, max_items_in_line: int = 70, sep: bool = True, apo: bool = False
129
+ ):
130
+ """
131
+ A function that wraps text into lines with a maximum number of items per line.
132
+
133
+ Args:
134
+ text (str | list): The input text or list of words to be wrapped.
135
+ max_items_in_line (int): The maximum number of items allowed in each line.
136
+ sep (bool, optional): Whether to include a comma separator between items. Defaults to True.
137
+ apo (bool, optional): Whether to enclose each word in single quotes. Defaults to False.
138
+ """
139
+
140
+ # * check if text is string, then strip and build word list
141
+ is_text = isinstance(text, str)
142
+ if is_text:
143
+ text = (
144
+ text.replace(",", "")
145
+ .replace("'", "")
146
+ .replace("[", "")
147
+ .replace("]", "")
148
+ .split(" ")
149
+ )
150
+
151
+ # * start
152
+ i = 0
153
+ line = ""
154
+
155
+ # * loop through words
156
+ out = ""
157
+ for word in text:
158
+ apo_s = "'" if apo else ""
159
+ sep_s = "," if sep and not is_text else ""
160
+ word_s = f"{apo_s}{str(word)}{apo_s}{sep_s}"
161
+ # * inc counter
162
+ i = i + len(word_s)
163
+ # * construct print line
164
+ line = line + word_s + " "
165
+ # * reset if counter exceeds limit
166
+ if i >= max_items_in_line:
167
+ out = out + line + "\n"
168
+ line = ""
169
+ i = 0
170
+ # else:
171
+ # * on short lists no reset happens, trigger manually
172
+ out = line if not out else out
173
+ # * cut last newline
174
+ return f"[{out[:-1]}]"
175
+
176
+
177
+ def create_barcode_from_url(
178
+ url: str,
179
+ output_path: str | None = None,
180
+ show_image: bool = False,
181
+ ):
182
+ WIDTH = 400
183
+ HEIGHT = 400
184
+
185
+ if not re.match(URL_REGEX, url):
186
+ print("❌ Not a valid URL")
187
+ return
188
+
189
+ image = requests.get(
190
+ f"https://chart.googleapis.com/chart?chs={WIDTH}x{HEIGHT}&cht=qr&chl={url}"
191
+ )
192
+ image.raise_for_status()
193
+
194
+ # * write binary content to file
195
+ if output_path:
196
+ with open(output_path, "wb") as qr:
197
+ qr.write(image.content)
198
+
199
+ # * Load the image from the response content
200
+ if show_image:
201
+ img = Image.open(BytesIO(image.content))
202
+ plt.imshow(img)
203
+ # plt.axis('off') # Turn off axis numbers
204
+ plt.show()