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/getColors.py ADDED
@@ -0,0 +1,399 @@
1
+ # getColors.py — analog of getColors.R.
2
+ #
3
+ # getColors(): generate a color palette and return it as a list of
4
+ # hex strings, printing a small table of the colors unless quiet.
5
+ # The HCL families (hues/qualitative, sequential, divergent) are
6
+ # reproduced exactly from R's grDevices HCL and colorspace
7
+ # trajectories; the manual families interpolate in RGB; Okabe-Ito,
8
+ # Tableau and "distinct" are fixed lists. The viridis family maps
9
+ # to plotly's built-in colorscales (a documented approximation),
10
+ # and R's wesanderson palettes are not ported (external package).
11
+
12
+ import math
13
+
14
+ # --- fixed palettes -------------------------------------------------
15
+
16
+ # Okabe-Ito, in R's order minus the leading black, black appended
17
+ _OKABE_ITO = [
18
+ "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2",
19
+ "#D55E00", "#CC79A7", "#999999", "#000000",
20
+ ]
21
+ _TABLEAU = [
22
+ "#4E79A7", "#F28E2B", "#E15759", "#76B7B2", "#59A14F",
23
+ "#EDC949", "#AF7AA1", "#FF9DA7", "#9C755F", "#BAB0AC",
24
+ ]
25
+ # R's "distinct" names resolved to hex (col2rgb)
26
+ _DISTINCT = [
27
+ "#EEB422", "#737373", "#9ACD32", "#CD69C9", "#87CEEB",
28
+ "#A9A9A9", "#F08080", "#8B795E", "#00CDCD", "#CD6600",
29
+ "#CD2990", "#66CDAA", "#4876FF", "#8B7D7B", "#CDB5CD",
30
+ ]
31
+
32
+ # hue (degrees) of each pre-defined HCL color sequence
33
+ _SEQ_HUE = {
34
+ "reds": 0, "rusts": 30, "browns": 60, "olives": 90,
35
+ "greens": 120, "emeralds": 150, "turquoises": 180,
36
+ "aquas": 210, "blues": 240, "purples": 270, "violets": 300,
37
+ "magentas": 330, "grays": 0,
38
+ }
39
+ _SEQ_NAMES = list(_SEQ_HUE)
40
+ _VIRIDIS = {"viridis": "Viridis", "cividis": "Cividis",
41
+ "plasma": "Plasma", "spectral": "Spectral"}
42
+
43
+ # D65 white point (grDevices HCL / colorspace polarLUV)
44
+ _XN, _YN, _ZN = 95.047, 100.0, 108.883
45
+
46
+
47
+ # --- HCL -> sRGB (grDevices polarLUV, D65) --------------------------
48
+
49
+ def _gtrans(u):
50
+ if u > 0.0031308:
51
+ return 1.055 * u ** (1.0 / 2.4) - 0.055
52
+ return 12.92 * u
53
+
54
+
55
+ def hcl(h, c, l, fixup=True):
56
+ """One HCL (polarLUV) color as a hex string, matching R's
57
+ grDevices::hcl. Returns None when out of gamut and fixup is
58
+ False. R analog: hcl()"""
59
+ if l <= 0:
60
+ x = y = z = 0.0
61
+ else:
62
+ hrad = math.radians(h)
63
+ U = c * math.cos(hrad)
64
+ V = c * math.sin(hrad)
65
+ un = 4 * _XN / (_XN + 15 * _YN + 3 * _ZN)
66
+ vn = 9 * _YN / (_XN + 15 * _YN + 3 * _ZN)
67
+ if l > 7.999592:
68
+ y = _YN * ((l + 16) / 116) ** 3
69
+ else:
70
+ y = _YN * l / 903.3
71
+ up = U / (13 * l) + un
72
+ vp = V / (13 * l) + vn
73
+ x = 9 * y * up / (4 * vp)
74
+ z = y * (12 - 3 * up - 20 * vp) / (4 * vp)
75
+
76
+ xr, yr, zr = x / 100, y / 100, z / 100
77
+ r = 3.240479 * xr - 1.537150 * yr - 0.498535 * zr
78
+ g = -0.969256 * xr + 1.875992 * yr + 0.041556 * zr
79
+ b = 0.055648 * xr - 0.204043 * yr + 1.057311 * zr
80
+ rgb = [_gtrans(max(0.0, v)) for v in (r, g, b)]
81
+
82
+ if not fixup and any(v < -1e-6 or v > 1 + 1e-6 for v in rgb):
83
+ return None
84
+ ints = [min(255, max(0, round(v * 255))) for v in rgb]
85
+ return "#{:02X}{:02X}{:02X}".format(*ints)
86
+
87
+
88
+ def _seq(n):
89
+ if n == 1:
90
+ return [0.0]
91
+ return [1.0 - i / (n - 1) for i in range(n)]
92
+
93
+
94
+ def _sequential_hcl(n, h, c, l, power, fixup):
95
+ c1, c2 = (c, c) if not isinstance(c, tuple) else c
96
+ l1, l2 = (l, l) if not isinstance(l, tuple) else l
97
+ p1, p2 = (power, power) if not isinstance(power, tuple) else power
98
+ out = []
99
+ for r in _seq(n):
100
+ L = l2 - (l2 - l1) * r ** p2
101
+ C = c2 - (c2 - c1) * r ** p1
102
+ out.append(hcl(h, C, L, fixup) + "FF")
103
+ return out
104
+
105
+
106
+ def _diverging_hcl(n, h1, h2, c, l, power, fixup):
107
+ l1, l2 = (l, l) if not isinstance(l, tuple) else l
108
+ p1, p2 = (power, power) if not isinstance(power, tuple) else power
109
+ rvals = [1.0] if n == 1 else \
110
+ [1.0 - 2.0 * i / (n - 1) for i in range(n)]
111
+ out = []
112
+ for r in rvals:
113
+ L = l2 - (l2 - l1) * abs(r) ** p2
114
+ C = c * abs(r) ** p1
115
+ H = h1 if r > 0 else h2
116
+ out.append(hcl(H, C, L, fixup) + "FF")
117
+ return out
118
+
119
+
120
+ # --- RGB ramp (colorRampPalette default space="rgb") ----------------
121
+
122
+ def _to_rgb(col):
123
+ from .plotly_utils import to_hex, hex_to_rgb3
124
+ return hex_to_rgb3(to_hex(col))
125
+
126
+
127
+ def _rgb_to_hcl(r, g, b):
128
+ """sRGB (0-255) -> HCL (polarLUV, D65): (hue_deg, chroma, lum).
129
+ The inverse of hcl(); used to read a named color's hue and
130
+ chroma for the value-scaled bar fills."""
131
+ def inv(v):
132
+ v /= 255.0
133
+ return (((v + 0.055) / 1.055) ** 2.4 if v > 0.04045
134
+ else v / 12.92)
135
+ R, G, B = inv(r), inv(g), inv(b)
136
+ X = (0.412453 * R + 0.357580 * G + 0.180423 * B) * 100
137
+ Y = (0.212671 * R + 0.715160 * G + 0.072169 * B) * 100
138
+ Z = (0.019334 * R + 0.119193 * G + 0.950227 * B) * 100
139
+ if Y <= 0:
140
+ return 0.0, 0.0, 0.0
141
+ yr = Y / _YN
142
+ L = (116 * yr ** (1 / 3) - 16 if yr > 0.008856 else 903.3 * yr)
143
+ d = X + 15 * Y + 3 * Z
144
+ if d == 0:
145
+ return 0.0, 0.0, L
146
+ un = 4 * _XN / (_XN + 15 * _YN + 3 * _ZN)
147
+ vn = 9 * _YN / (_XN + 15 * _YN + 3 * _ZN)
148
+ U = 13 * L * (4 * X / d - un)
149
+ V = 13 * L * (9 * Y / d - vn)
150
+ return math.degrees(math.atan2(V, U)) % 360, math.hypot(U, V), L
151
+
152
+
153
+ def _color_hc(col):
154
+ h, c, _ = _rgb_to_hcl(*_to_rgb(col))
155
+ return h, c
156
+
157
+
158
+ def bar_fill_colors(values, fill, fill_split, fill_scaled,
159
+ fill_chroma=75):
160
+ """Per-bar fill colors for a numeric bar chart, keyed to the bar
161
+ values. fill_split gives a two-color split at that value (below
162
+ -> first color, above -> second). fill_scaled makes an HCL
163
+ gradient: chroma and darkness rise with distance from the split
164
+ (default 0), hue by side. A faithful approximation of R's
165
+ .scale.clr, not colorspace-exact. R analog: fill_split /
166
+ fill_scaled."""
167
+ import numpy as np
168
+ from .plotly_utils import to_hex
169
+ x = np.asarray(values, dtype=float)
170
+ fills = (None if fill is None
171
+ else [fill] if isinstance(fill, str) else list(fill))
172
+ split = 0.0 if fill_split is None else float(fill_split)
173
+
174
+ if not fill_scaled: # discrete two-color split
175
+ if fills is not None and len(fills) == 2:
176
+ c1, c2 = to_hex(fills[0]), to_hex(fills[1])
177
+ else: # default dark/light pair
178
+ c1, c2 = hcl(255, 55, 30), hcl(255, 55, 70)
179
+ return [c1 if v <= split else c2 for v in x]
180
+
181
+ dist = np.abs(x - split)
182
+ mx = float(dist.max()) or 1.0
183
+ normed = dist / mx
184
+ lum = 27 + (1 - normed) * 53 # near split light, far dark
185
+
186
+ if fills is None or len(fills) > 2:
187
+ h1 = h2 = 255.0
188
+ c1 = c2 = float(fill_chroma)
189
+ elif len(fills) == 1:
190
+ h1, c1 = _color_hc(fills[0])
191
+ h2, c2 = h1, c1
192
+ else:
193
+ h1, c1 = _color_hc(fills[0])
194
+ h2, c2 = _color_hc(fills[1])
195
+ g1, g2 = c1 < 5, c2 < 5 # near-gray fill colors
196
+
197
+ out = []
198
+ for v, nm, L in zip(x, normed, lum):
199
+ if g1 and g2: # pure grayscale ramp
200
+ hue, chroma = 0.0, 0.0
201
+ elif g1 or g2: # sequential: chromatic hue
202
+ hue = h2 if g1 else h1
203
+ chroma = (c2 if g1 else c1) * nm
204
+ else: # diverging by side
205
+ below = v <= split
206
+ hue = h1 if below else h2
207
+ chroma = (c1 if below else c2) * nm
208
+ out.append(hcl(hue, chroma, max(1.0, L)))
209
+ return out
210
+
211
+
212
+ def _ramp(colors, n):
213
+ pts = [_to_rgb(c) for c in colors]
214
+ if n == 1:
215
+ r, g, b = pts[0]
216
+ return ["#{:02X}{:02X}{:02X}".format(r, g, b)]
217
+ m = len(pts) - 1
218
+ out = []
219
+ for i in range(n):
220
+ t = i / (n - 1) * m
221
+ j = min(int(math.floor(t)), m - 1)
222
+ f = t - j
223
+ rgb = [round(pts[j][k] + f * (pts[j + 1][k] - pts[j][k]))
224
+ for k in range(3)]
225
+ out.append("#{:02X}{:02X}{:02X}".format(*rgb))
226
+ return out
227
+
228
+
229
+ def _viridis(name, n):
230
+ from plotly.colors import sample_colorscale
231
+ xs = [0.0] if n == 1 else [i / (n - 1) for i in range(n)]
232
+ cols = sample_colorscale(_VIRIDIS[name], xs, colortype="rgb")
233
+ out = []
234
+ for c in cols:
235
+ r, g, b = (round(float(v)) for v in
236
+ c[c.find("(") + 1:c.find(")")].split(","))
237
+ out.append("#{:02X}{:02X}{:02X}".format(r, g, b))
238
+ return out
239
+
240
+
241
+ # the fixed mixed hues for a qualitative palette (n <= 24)
242
+ _MIX = [240, 60, 120, 0, 275, 180, 30, 90, 210, 330, 150, 300]
243
+
244
+
245
+ def getColors(pal=None, end_pal=None, n=None, h=0, h2=None, c=None,
246
+ l=None, in_order=None, fixup=True, power=None,
247
+ transparency=0, quiet=False):
248
+ """Generate a color palette, returning a list of hex colors and
249
+ (unless quiet) printing a table of them.
250
+
251
+ pal: a palette name ("hues", a sequential name such as "blues",
252
+ "viridis"/"cividis"/"plasma"/"spectral", "Okabe-Ito", "Tableau",
253
+ "distinct") or one or more explicit colors. end_pal: an ending
254
+ color/name for a divergent (two sequential names) or manual
255
+ (two colors) gradient. h/h2, c, l, power: HCL parameters.
256
+ R analog: getColors()"""
257
+ c_miss, l_miss = c is None, l is None
258
+ n_miss = n is None
259
+ if n_miss:
260
+ n = 12
261
+
262
+ if in_order is None:
263
+ in_order = False
264
+ if isinstance(pal, str):
265
+ pal = [pal]
266
+ if isinstance(pal, list) and pal and pal[0] == "yellows":
267
+ pal[0] = "browns"
268
+ if isinstance(pal, str) and pal == "magma":
269
+ pal = ["plasma"]
270
+
271
+ if pal is None and end_pal is None and not isinstance(c, list) \
272
+ and not isinstance(l, list):
273
+ pal = ["hues"]
274
+
275
+ # classify the request
276
+ if pal is not None:
277
+ p0 = pal[0]
278
+ if p0 in _SEQ_NAMES:
279
+ kind = "divergent" if (end_pal is not None and
280
+ end_pal[0] in _SEQ_NAMES) \
281
+ else "sequential"
282
+ elif p0 == "hues":
283
+ kind = "qualitative"
284
+ elif p0 in _VIRIDIS:
285
+ kind = "viridis"
286
+ elif p0 == "Okabe-Ito":
287
+ kind = "oi"
288
+ elif p0 == "Tableau":
289
+ kind = "Tableau"
290
+ elif p0 == "distinct":
291
+ kind = "distinct"
292
+ else:
293
+ kind = "manual.q" if end_pal is None else "manual.s"
294
+ else:
295
+ kind = "sequential" if (isinstance(c, list) or
296
+ isinstance(l, list)) else "qualitative"
297
+
298
+ # pre-defined sequential/divergent hues
299
+ if pal is not None and pal[0] in _SEQ_NAMES:
300
+ h = _SEQ_HUE[pal[0]]
301
+ if pal[0] == "grays":
302
+ c, c_miss = 0, False
303
+ if end_pal is None:
304
+ pal = None
305
+ if end_pal is not None and end_pal[0] in _SEQ_NAMES:
306
+ h2 = _SEQ_HUE[end_pal[0]]
307
+ if end_pal[0] == "grays":
308
+ c, c_miss = 0, False
309
+ pal = None
310
+
311
+ ttl = ""
312
+
313
+ if kind == "qualitative":
314
+ if h2 is None:
315
+ h2 = h + (360 * (n - 1) / n)
316
+ if n <= 24:
317
+ if not in_order:
318
+ hues = _MIX + [x + 15 for x in _MIX]
319
+ else:
320
+ hues = ([h] if n == 1 else
321
+ [h + (h2 - h) * i / (n - 1) for i in range(n)])
322
+ else:
323
+ hues = [h + (h2 - h) * i / (n - 1) for i in range(n)]
324
+ hues = [(x - 360 if x >= 360 else x + 360 if x < 0 else x)
325
+ for x in hues]
326
+ cc = 65 if c_miss else c
327
+ ll = 60 if l_miss else l
328
+ pal = [hcl(hues[i], cc, ll, fixup) for i in range(n)]
329
+
330
+ elif kind == "sequential":
331
+ cc = (35, 75) if c_miss else (c if isinstance(c, (tuple, list))
332
+ else (c, c))
333
+ l_dk = max(14, 35 - 3 * n)
334
+ l_lt = min(92, 52 + 5 * n)
335
+ ll = (l_lt, l_dk) if l_miss else (l if isinstance(l, (tuple,
336
+ list)) else (l, l))
337
+ pw = 1 if power is None else power
338
+ pal = _sequential_hcl(n, h, tuple(cc), tuple(ll), pw, fixup)
339
+
340
+ elif kind == "divergent":
341
+ cc = 50 if c_miss else (c[0] if isinstance(c, (tuple, list))
342
+ else c)
343
+ ll = (30, 80) if l_miss else (tuple(l) if isinstance(l, (tuple,
344
+ list)) else (l, l))
345
+ pw = 0.75 if power is None else power
346
+ pal = _diverging_hcl(n, h, h2, cc, ll, pw, fixup)
347
+
348
+ elif kind == "viridis":
349
+ ttl = "Viridis Style Palette: " + pal[0]
350
+ pal = _viridis(pal[0], n)
351
+
352
+ elif kind == "oi":
353
+ if n_miss:
354
+ n = 9
355
+ if n > 9:
356
+ raise ValueError("only 9 Okabe-Ito colors are available")
357
+ pal = _OKABE_ITO[:n]
358
+
359
+ elif kind == "Tableau":
360
+ if n_miss:
361
+ n = 10
362
+ if n > 10:
363
+ raise ValueError("only 10 Tableau colors are available")
364
+ pal = _TABLEAU[:n]
365
+
366
+ elif kind == "distinct":
367
+ if n > 15:
368
+ raise ValueError("only 15 distinct colors are available")
369
+ pal = _DISTINCT[:n]
370
+
371
+ elif kind == "manual.s":
372
+ anchors = list(pal) + list(
373
+ end_pal if isinstance(end_pal, list) else [end_pal])
374
+ pal = _ramp(anchors, n)
375
+
376
+ else: # manual.q
377
+ from .plotly_utils import to_hex
378
+ pal = [to_hex(c1) for c1 in pal]
379
+ n = len(pal)
380
+
381
+ if transparency > 0:
382
+ from .plotly_utils import make_trans
383
+ pal = [make_trans(col, 1 - transparency) for col in pal]
384
+
385
+ if not quiet:
386
+ _print_table(pal, kind)
387
+ return pal
388
+
389
+
390
+ def _print_table(pal, kind):
391
+ from .plotly_utils import to_hex, hex_to_rgb3
392
+ print()
393
+ print(" color r g b")
394
+ print("-----------------------------")
395
+ for i, col in enumerate(pal, 1):
396
+ r, g, b = hex_to_rgb3(to_hex(col))
397
+ print("{:>2} {:<9}{:>4} {:>4} {:>4}".format(
398
+ i, col, r, g, b))
399
+ print()