lessPython 0.1.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.
Files changed (82) hide show
  1. lessPy/ANOVA.py +680 -0
  2. lessPy/Chart.py +1055 -0
  3. lessPy/Correlation.py +236 -0
  4. lessPy/Flows.py +116 -0
  5. lessPy/Logit.py +615 -0
  6. lessPy/Prop_test.py +267 -0
  7. lessPy/Regression.py +1491 -0
  8. lessPy/VariableLabels.py +119 -0
  9. lessPy/X.py +426 -0
  10. lessPy/XY.py +2007 -0
  11. lessPy/__init__.py +60 -0
  12. lessPy/anova_rmd.py +227 -0
  13. lessPy/bc_plotly.py +575 -0
  14. lessPy/bubble_plotly.py +470 -0
  15. lessPy/corCFA.py +316 -0
  16. lessPy/corEFA.py +220 -0
  17. lessPy/corPrint.py +45 -0
  18. lessPy/corProp.py +73 -0
  19. lessPy/corRead.py +48 -0
  20. lessPy/corReflect.py +72 -0
  21. lessPy/corReorder.py +161 -0
  22. lessPy/corScree.py +87 -0
  23. lessPy/data/Anova_1way.csv +25 -0
  24. lessPy/data/Anova_2way.csv +49 -0
  25. lessPy/data/Anova_rb.csv +8 -0
  26. lessPy/data/Anova_rbf.csv +49 -0
  27. lessPy/data/Anova_sp.csv +57 -0
  28. lessPy/data/BodyMeas.csv +341 -0
  29. lessPy/data/Cars93.csv +94 -0
  30. lessPy/data/Employee.csv +38 -0
  31. lessPy/data/Employee_lbl.csv +9 -0
  32. lessPy/data/FreqTable99.csv +5 -0
  33. lessPy/data/Jackets.csv +1026 -0
  34. lessPy/data/Learn.csv +35 -0
  35. lessPy/data/Mach4.csv +352 -0
  36. lessPy/data/Mach4_lbl.csv +21 -0
  37. lessPy/data/Reading.csv +101 -0
  38. lessPy/data/StockPrice.csv +1489 -0
  39. lessPy/data/WeightLoss.csv +11 -0
  40. lessPy/datasets.py +46 -0
  41. lessPy/date_infer.py +112 -0
  42. lessPy/details.py +314 -0
  43. lessPy/dn_plotly.py +495 -0
  44. lessPy/dot_plotly.py +385 -0
  45. lessPy/freq_poly_plotly.py +324 -0
  46. lessPy/getColors.py +399 -0
  47. lessPy/hier_plotly.py +352 -0
  48. lessPy/hs_plotly.py +395 -0
  49. lessPy/logit_rmd.py +410 -0
  50. lessPy/order_by.py +94 -0
  51. lessPy/pie_plotly.py +292 -0
  52. lessPy/pivot.py +158 -0
  53. lessPy/plotly_utils.py +787 -0
  54. lessPy/plt_add.py +129 -0
  55. lessPy/plt_contour.py +192 -0
  56. lessPy/plt_contour_facet.py +194 -0
  57. lessPy/plt_forecast.py +677 -0
  58. lessPy/plt_mat_plotly.py +201 -0
  59. lessPy/plt_plotly.py +216 -0
  60. lessPy/plt_smooth.py +170 -0
  61. lessPy/plt_time.py +143 -0
  62. lessPy/prob_norm.py +111 -0
  63. lessPy/prob_tcut.py +131 -0
  64. lessPy/prob_znorm.py +110 -0
  65. lessPy/radar_plotly.py +201 -0
  66. lessPy/reg_rmd.py +754 -0
  67. lessPy/rename.py +33 -0
  68. lessPy/reshape.py +95 -0
  69. lessPy/showColors.py +130 -0
  70. lessPy/simCImean.py +165 -0
  71. lessPy/simCLT.py +265 -0
  72. lessPy/simFlips.py +104 -0
  73. lessPy/simMeans.py +146 -0
  74. lessPy/stats_out.py +189 -0
  75. lessPy/ttest.py +641 -0
  76. lessPy/utils.py +235 -0
  77. lessPy/vbs_plotly.py +545 -0
  78. lesspython-0.1.0.dist-info/METADATA +93 -0
  79. lesspython-0.1.0.dist-info/RECORD +82 -0
  80. lesspython-0.1.0.dist-info/WHEEL +5 -0
  81. lesspython-0.1.0.dist-info/licenses/LICENSE +338 -0
  82. lesspython-0.1.0.dist-info/top_level.txt +1 -0
lessPy/dot_plotly.py ADDED
@@ -0,0 +1,385 @@
1
+ # dot_plotly.py — analog of dot.plotly.R
2
+ #
3
+ # Renders a Cleveland dot chart from ALREADY-AGGREGATED input:
4
+ # single-series cats + 1-D vals: one dot per category, with an
5
+ # origin->value stem ("lollipop") per dot
6
+ # paired cats + DataFrame vals (2+ numeric columns): one
7
+ # series per column, horizontal, with a legend
8
+ # (e.g., x=Name, y=[Pre, Post])
9
+ # faceted cats + vals + facet= (one level per
10
+ # observation): a grid of single-series panels,
11
+ # one per facet level, on a shared value axis
12
+ # with dot hues keyed by category name
13
+
14
+ import numpy as np
15
+ import pandas as pd
16
+ import plotly.graph_objects as go
17
+
18
+ from .utils import get_option
19
+ from .plotly_utils import (
20
+ BASE_COLORS, axis_cat, axis_format, axis_num, facet_layout,
21
+ get_tick_fmt, make_trans, plot_border, plotly_style, to_hex,
22
+ x_grid, y_grid,
23
+ )
24
+
25
+ # R plotting shape codes -> plotly symbol names
26
+ _SYMBOLS = {21: "circle", 22: "square", 23: "diamond",
27
+ 24: "triangle-up", 25: "triangle-down"}
28
+
29
+
30
+ def _marker_style(shape, pt_size, fill, border, pt_opacity):
31
+ """Per-point marker geometry. R analog: .dot_marker_style()"""
32
+ px = float(pt_size) * 10
33
+ if not np.isfinite(px) or px <= 0:
34
+ px = 5
35
+ fill1 = fill[0] if isinstance(fill, (list, tuple)) else fill
36
+ border1 = (border[0] if isinstance(border, (list, tuple))
37
+ else border)
38
+ return {
39
+ "symbol": _SYMBOLS.get(shape, "circle"),
40
+ "px": px,
41
+ "color": make_trans(fill1, pt_opacity),
42
+ "border": to_hex(border1),
43
+ }
44
+
45
+
46
+ def _marker_list(ms, n, color_override=None):
47
+ """marker= dict for a scatter trace. R analog: .dot_marker_list()"""
48
+ return dict(
49
+ symbol=ms["symbol"],
50
+ size=[ms["px"]] * n,
51
+ sizemode="diameter",
52
+ color=(ms["color"] if color_override is None
53
+ else color_override),
54
+ opacity=1,
55
+ line=dict(color=ms["border"], width=1),
56
+ )
57
+
58
+
59
+ def _add_marker_trace(fig, cats, vals, marker, orientation,
60
+ hover_tmpl=None, name=None, showlegend=False,
61
+ axis_suf=""):
62
+ """R analog: .dot_marker_trace()"""
63
+ xv, yv = (cats, vals) if orientation == "v" else (vals, cats)
64
+ kw = dict(mode="markers", x=xv, y=yv, marker=marker,
65
+ showlegend=showlegend,
66
+ xaxis=f"x{axis_suf}", yaxis=f"y{axis_suf}")
67
+ if hover_tmpl is not None:
68
+ kw["hovertemplate"] = hover_tmpl
69
+ if name is not None:
70
+ kw["name"] = name
71
+ fig.add_trace(go.Scatter(**kw))
72
+
73
+
74
+ def _add_segment_trace(fig, cats, vals, seg_color, orientation,
75
+ seg_start, axis_suf=""):
76
+ """None-separated origin->value stems; cats/vals must be
77
+ pre-filtered to finite values. R analog: .dot_segment_trace()"""
78
+ n = len(vals)
79
+ if n == 0:
80
+ return
81
+ seg_cat, seg_val = [], []
82
+ for c, v in zip(cats, vals):
83
+ seg_cat += [c, c, None]
84
+ seg_val += [seg_start, v, None]
85
+ if orientation == "v":
86
+ seg_x, seg_y = seg_cat, seg_val
87
+ else:
88
+ seg_x, seg_y = seg_val, seg_cat
89
+ fig.add_trace(go.Scatter(
90
+ mode="lines", x=seg_x, y=seg_y,
91
+ xaxis=f"x{axis_suf}", yaxis=f"y{axis_suf}",
92
+ line=dict(color=seg_color, width=1),
93
+ hoverinfo="skip", showlegend=False,
94
+ ))
95
+
96
+
97
+ def _val_axis(label, gridT, origin_x, ticktext=None):
98
+ """Numeric (value) axis spec. R analog: .dot_val_axis()"""
99
+ ax = axis_num(label, gridT, ticktext)
100
+ if origin_x is not None and gridT:
101
+ step = gridT[1] - gridT[0] if len(gridT) > 1 else 0
102
+ ax["range"] = [min(origin_x, min(gridT)), max(gridT) + step]
103
+ ax["autorange"] = False
104
+ return ax
105
+
106
+
107
+ def _cat_axis(label, cats):
108
+ """Category axis, order frozen. R analog: .dot_cat_axis()"""
109
+ ax = axis_cat(label)
110
+ ax.update(categoryorder="array", categoryarray=cats,
111
+ tickmode="array", tickvals=cats, ticktext=cats)
112
+ return ax
113
+
114
+
115
+ def _dot_title(main):
116
+ """R analog: .dot_title()"""
117
+ if not main:
118
+ return None
119
+ return dict(text=main, x=0.5, xanchor="center",
120
+ y=0.98, yanchor="top",
121
+ font=dict(size=round(16 * get_option("main_size", 1)),
122
+ color=to_hex(get_option("lab_color",
123
+ "black"))))
124
+
125
+
126
+ def _hover(orientation, x_lab, y_lab, val_spec):
127
+ if orientation == "v":
128
+ cat_label = x_lab or "Category"
129
+ val_label = y_lab or "Value"
130
+ return (f"{cat_label}: %{{x}}<br>"
131
+ f"{val_label}: %{{y{val_spec}}}<extra></extra>")
132
+ cat_label = y_lab or "Category"
133
+ val_label = x_lab or "Value"
134
+ return (f"{val_label}: %{{x{val_spec}}}<br>"
135
+ f"{cat_label}: %{{y}}<extra></extra>")
136
+
137
+
138
+ def dot_plotly(x, y, orientation="v",
139
+ fill=None, border=None, shape=21, pt_size=1,
140
+ x_lab="", y_lab="", digits_d=2, pt_opacity=0.95,
141
+ gridT=None, origin_x=None, main=None,
142
+ facet=None, facet_name=None, n_col=None,
143
+ axis_fmt="K", axis_x_pre="", axis_y_pre="",
144
+ rotate_x=0, rotate_y=0,
145
+ segments_x=True, segments_y=True, style_opts=None):
146
+
147
+ cats, vals = x, y
148
+ if style_opts is None:
149
+ style_opts = plotly_style()
150
+ if fill is None:
151
+ fill = BASE_COLORS
152
+ if border is None:
153
+ border = get_option("pt_color", "#324E5C")
154
+
155
+ title_size = round(16 * get_option("main_size", 1))
156
+ seg_color = to_hex(style_opts["segment_color"])
157
+
158
+ def val_ticks(orient):
159
+ # value-axis labels through the axis_fmt policies ("60K"),
160
+ # prefixed for the physical axis the values land on
161
+ if not gridT:
162
+ return None
163
+ return axis_format(gridT, digits_d, axis_fmt,
164
+ axis_x_pre if orient == "h"
165
+ else axis_y_pre)
166
+
167
+ def apply_rotate(x_ax, y_ax):
168
+ if rotate_x:
169
+ x_ax["tickangle"] = -rotate_x
170
+ if rotate_y:
171
+ y_ax["tickangle"] = -rotate_y
172
+
173
+ # ---- paired dot plot (vals is a DataFrame, 2+ columns) --------
174
+ # Single panel, cats on y, values on x; one legend entry per
175
+ # y column.
176
+ if isinstance(vals, pd.DataFrame):
177
+ cats_all = [str(c) for c in cats]
178
+ ms = _marker_style(21, pt_size, fill, border, pt_opacity)
179
+ seg_start = 0 if origin_x is None else origin_x
180
+
181
+ fig = go.Figure()
182
+ for si, col in enumerate(vals.columns):
183
+ vals_si = vals[col].to_numpy(dtype=float)
184
+ fill_si = (fill[si % len(fill)]
185
+ if isinstance(fill, (list, tuple)) else fill)
186
+ clr = make_trans(fill_si, pt_opacity)
187
+ if segments_x:
188
+ fin = np.isfinite(vals_si)
189
+ _add_segment_trace(
190
+ fig, [c for c, f in zip(cats_all, fin) if f],
191
+ vals_si[fin].tolist(), seg_color, "h",
192
+ seg_start)
193
+ _add_marker_trace(
194
+ fig, cats_all, vals_si.tolist(),
195
+ marker=_marker_list(ms, len(vals_si),
196
+ color_override=clr),
197
+ orientation="h", name=str(col), showlegend=True)
198
+
199
+ x_ax = _val_axis(x_lab, gridT, origin_x, val_ticks("h"))
200
+ y_ax = _cat_axis(y_lab, cats_all)
201
+ apply_rotate(x_ax, y_ax)
202
+ fig.update_layout(
203
+ xaxis=x_ax,
204
+ yaxis=y_ax,
205
+ shapes=(x_grid(gridT) if gridT else []) + plot_border(),
206
+ margin=dict(t=round(title_size * 2.2) if main else 30),
207
+ title=_dot_title(main),
208
+ legend=dict(font=dict(size=round(
209
+ 16 * get_option("axis_size", 0.9)))),
210
+ template=None,
211
+ plot_bgcolor=to_hex(style_opts["panel_fill"]),
212
+ paper_bgcolor=to_hex(style_opts["window_fill"]),
213
+ )
214
+ return fig
215
+
216
+ # ---- faceted dot plot --------------------------------------------
217
+ # Grid of single-series panels, one per facet level, on a shared
218
+ # value axis. Per-panel segment start is clamped at-or-below the
219
+ # panel minimum so dots never sit to the left of (or below)
220
+ # their stem. R analog: dot.plotly.R faceted path
221
+ if facet is not None:
222
+ fac_char = [None if f is None
223
+ or (isinstance(f, float) and np.isnan(f))
224
+ else str(f) for f in facet]
225
+ fac_levels = sorted({f for f in fac_char if f is not None})
226
+
227
+ cats_in = [str(c) for c in cats]
228
+ vals_in = np.asarray(list(vals), dtype=float)
229
+
230
+ ms = _marker_style(shape, pt_size, fill, border,
231
+ pt_opacity)
232
+ # color keyed by category name so hues match across panels
233
+ cat_levels = list(dict.fromkeys(cats_in))
234
+ col_map = {c: make_trans(
235
+ to_hex(fill[i % len(fill)]
236
+ if isinstance(fill, (list, tuple))
237
+ else fill),
238
+ pt_opacity)
239
+ for i, c in enumerate(cat_levels)}
240
+
241
+ val_fmt = get_tick_fmt(vals_in[np.isfinite(vals_in)],
242
+ digits_d)
243
+ val_spec = f":{val_fmt}" if val_fmt else ""
244
+ hover_tmpl = _hover(orientation, x_lab, y_lab, val_spec)
245
+ draw_seg = segments_x if orientation == "h" else segments_y
246
+
247
+ def ann_adj(i, a, d):
248
+ a["y"] = min(d["y"][1] + 0.04, 0.99)
249
+ return a
250
+ domains, anns = facet_layout(
251
+ fac_levels, facet_name or "",
252
+ yanchor="bottom", ann_adjust=ann_adj, n_col=n_col)
253
+
254
+ fig = go.Figure()
255
+ axes = {}
256
+ for i, lv in enumerate(fac_levels):
257
+ suf = "" if i == 0 else str(i + 1)
258
+ keep = [k for k, f in enumerate(fac_char) if f == lv]
259
+ cats_i = [cats_in[k] for k in keep]
260
+ vals_i = vals_in[keep]
261
+ fin = np.isfinite(vals_i)
262
+
263
+ if fin.any() and draw_seg:
264
+ # never above the panel's data minimum — avoid
265
+ # backward stems
266
+ panel_min = float(vals_i[fin].min())
267
+ seg_start = (min(origin_x, panel_min)
268
+ if origin_x is not None else 0)
269
+ _add_segment_trace(
270
+ fig, [c for c, f in zip(cats_i, fin) if f],
271
+ vals_i[fin].tolist(), seg_color, orientation,
272
+ seg_start, axis_suf=suf)
273
+ _add_marker_trace(
274
+ fig, cats_i,
275
+ [None if not np.isfinite(v) else v
276
+ for v in vals_i],
277
+ marker=_marker_list(
278
+ ms, len(vals_i),
279
+ color_override=[col_map[c] for c in cats_i]),
280
+ orientation=orientation, hover_tmpl=hover_tmpl,
281
+ axis_suf=suf)
282
+
283
+ val_lbl = x_lab if orientation == "h" else y_lab
284
+ cat_lbl = y_lab if orientation == "h" else x_lab
285
+ val_ax = _val_axis(val_lbl if i == 0 else "",
286
+ gridT, origin_x,
287
+ val_ticks(orientation))
288
+ cat_ax = _cat_axis(cat_lbl, cats_i)
289
+ x_ax, y_ax = ((val_ax, cat_ax)
290
+ if orientation == "h"
291
+ else (cat_ax, val_ax))
292
+ apply_rotate(x_ax, y_ax)
293
+ x_ax.update(domain=list(domains[i]["x"]),
294
+ anchor=f"y{suf}")
295
+ y_ax.update(domain=list(domains[i]["y"]),
296
+ anchor=f"x{suf}")
297
+ axes[f"xaxis{suf}"] = x_ax
298
+ axes[f"yaxis{suf}"] = y_ax
299
+
300
+ fig.update_layout(
301
+ annotations=anns,
302
+ margin=dict(t=round(title_size * 2.2) if main else 40,
303
+ b=8, l=20, r=20),
304
+ showlegend=False,
305
+ title=_dot_title(main),
306
+ template=None,
307
+ plot_bgcolor=to_hex(style_opts["panel_fill"]),
308
+ paper_bgcolor=to_hex(style_opts["window_fill"]),
309
+ **axes,
310
+ )
311
+ return fig
312
+
313
+ # ---- single-series dot plot ------------------------------------
314
+ pt_opacity = float(pt_opacity)
315
+ if not np.isfinite(pt_opacity):
316
+ pt_opacity = 0.95
317
+ pt_opacity = max(0.0, min(1.0, pt_opacity))
318
+
319
+ pairs = [(str(c), v) for c, v in zip(cats, vals)
320
+ if c is not None and not (isinstance(c, float)
321
+ and np.isnan(c))]
322
+ if not pairs:
323
+ return go.Figure()
324
+ cats = [p[0] for p in pairs]
325
+ vals = np.array([p[1] for p in pairs], dtype=float)
326
+ cats_all = list(cats) # full list for categoryarray
327
+
328
+ ms = _marker_style(shape, pt_size, fill, border, pt_opacity)
329
+
330
+ val_fmt = get_tick_fmt(vals[np.isfinite(vals)], digits_d)
331
+ val_spec = f":{val_fmt}" if val_fmt else ""
332
+ hover_tmpl = _hover(orientation, x_lab, y_lab, val_spec)
333
+
334
+ fig = go.Figure()
335
+ # segments first so dots sit on top
336
+ draw_seg = segments_x if orientation == "h" else segments_y
337
+ if draw_seg:
338
+ fin = np.isfinite(vals)
339
+ _add_segment_trace(
340
+ fig, [c for c, f in zip(cats, fin) if f],
341
+ vals[fin].tolist(), seg_color, orientation,
342
+ seg_start=0 if origin_x is None else origin_x)
343
+
344
+ # one palette color per category, same hues as the bar chart
345
+ pt_cols = make_trans(
346
+ to_hex([fill[i % len(fill)] if isinstance(fill, (list, tuple))
347
+ else fill for i in range(len(vals))]),
348
+ pt_opacity)
349
+ _add_marker_trace(
350
+ fig, cats, [None if not np.isfinite(v) else v for v in vals],
351
+ marker=_marker_list(ms, len(vals), color_override=pt_cols),
352
+ orientation=orientation, hover_tmpl=hover_tmpl)
353
+
354
+ # grid lines run perpendicular to the value axis
355
+ if gridT:
356
+ grid_shapes = (y_grid(gridT) if orientation == "v"
357
+ else x_grid(gridT))
358
+ else:
359
+ grid_shapes = []
360
+ cat_ax = _cat_axis(x_lab if orientation == "v" else y_lab,
361
+ cats_all)
362
+ val_ax = _val_axis(x_lab if orientation == "h" else y_lab,
363
+ gridT, origin_x, val_ticks(orientation))
364
+
365
+ if orientation == "h":
366
+ margin = dict(l=70,
367
+ t=round(title_size * 2.2) if main else 30,
368
+ b=max(40, 60 if x_lab else 0))
369
+ apply_rotate(val_ax, cat_ax)
370
+ fig.update_layout(xaxis=val_ax, yaxis=cat_ax)
371
+ else:
372
+ margin = dict(t=round(title_size * 2.2) if main else 30,
373
+ b=max(12, 60 if x_lab else 0))
374
+ apply_rotate(cat_ax, val_ax)
375
+ fig.update_layout(xaxis=cat_ax, yaxis=val_ax)
376
+
377
+ fig.update_layout(
378
+ shapes=grid_shapes + plot_border(),
379
+ margin=margin,
380
+ title=_dot_title(main),
381
+ template=None,
382
+ plot_bgcolor=to_hex(style_opts["panel_fill"]),
383
+ paper_bgcolor=to_hex(style_opts["window_fill"]),
384
+ )
385
+ return fig