lessPython 0.2.0__py3-none-any.whl → 0.3.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.
- lessPy/ANOVA.py +5 -5
- lessPy/Chart.py +386 -88
- lessPy/Correlation.py +2 -2
- lessPy/Logit.py +2 -2
- lessPy/Regression.py +6 -4
- lessPy/X.py +279 -42
- lessPy/XY.py +814 -158
- lessPy/__init__.py +12 -2
- lessPy/_themes.py +5007 -0
- lessPy/bc_items_plotly.py +31 -18
- lessPy/bc_plotly.py +23 -7
- lessPy/bubble_plotly.py +17 -2
- lessPy/corCFA.py +3 -3
- lessPy/corProp.py +2 -2
- lessPy/corReflect.py +2 -2
- lessPy/corReorder.py +2 -2
- lessPy/corScree.py +3 -3
- lessPy/data/StockPrice.csv +1401 -1386
- lessPy/details.py +17 -4
- lessPy/dn_plotly.py +65 -45
- lessPy/freq_poly_plotly.py +12 -5
- lessPy/getColors.py +247 -20
- lessPy/hier_plotly.py +36 -9
- lessPy/hs_plotly.py +16 -4
- lessPy/plotly_utils.py +78 -9
- lessPy/plt_mat_plotly.py +74 -2
- lessPy/plt_time.py +10 -3
- lessPy/prob_norm.py +3 -3
- lessPy/prob_tcut.py +3 -3
- lessPy/prob_znorm.py +3 -1
- lessPy/rcolors.py +461 -0
- lessPy/simCImean.py +3 -3
- lessPy/simCLT.py +3 -3
- lessPy/simFlips.py +3 -3
- lessPy/simMeans.py +3 -3
- lessPy/stats_out.py +257 -11
- lessPy/style.py +160 -0
- lessPy/sunflower_plotly.py +140 -0
- lessPy/ttest.py +5 -5
- lessPy/utils.py +43 -6
- lessPy/vbs_plotly.py +16 -5
- lessPy/x_console.py +763 -0
- {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/METADATA +6 -2
- lesspython-0.3.0.dist-info/RECORD +89 -0
- lesspython-0.2.0.dist-info/RECORD +0 -84
- {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/WHEEL +0 -0
- {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/top_level.txt +0 -0
lessPy/bc_items_plotly.py
CHANGED
|
@@ -20,7 +20,7 @@ from .utils import get_option, pretty
|
|
|
20
20
|
from .plotly_utils import (
|
|
21
21
|
as_plotly_color, auto_text_color, axis_cat, axis_format,
|
|
22
22
|
axis_num, legend_style, plot_border, plotly_style, to_hex,
|
|
23
|
-
x_grid,
|
|
23
|
+
x_grid, y_grid,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
# theme -> the two sequential palettes of the divergent fill
|
|
@@ -91,24 +91,31 @@ def items_table(cols, names):
|
|
|
91
91
|
return frq, wm, numeric
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-
def items_stats_lines(frq, wm, title, numeric=True):
|
|
94
|
+
def items_stats_lines(frq, wm, title, numeric=True, with_sum=False):
|
|
95
95
|
"""'Frequencies of Responses by Variable': one row per item,
|
|
96
96
|
its counts and its mean. R analog: .prntbl(t(x), 0) with the
|
|
97
|
-
Mean column of .bc.main() multi
|
|
98
|
-
|
|
97
|
+
Mean column of .bc.main() multi. with_sum adds the Sum column of
|
|
98
|
+
the bubble plot frequency matrix, whose Mean column follows at
|
|
99
|
+
one space and is sized to the mean at three decimals, as
|
|
100
|
+
.dpmat.main() writes it"""
|
|
101
|
+
t = frq.T.copy()
|
|
102
|
+
if with_sum:
|
|
103
|
+
t["Sum"] = t.sum(axis=1)
|
|
99
104
|
rows = [str(r) for r in t.index]
|
|
100
105
|
max_c1 = max(len(r) for r in rows) + 2
|
|
101
106
|
widths = [max(4, max(len(str(c)),
|
|
102
107
|
max(len(f"{v:.0f}") for v in t[c])) + 1)
|
|
103
108
|
for c in t.columns]
|
|
104
|
-
mx = max(len(f"{round(v, 2):.15g}")
|
|
109
|
+
mx = max(len(f"{round(v, 3 if with_sum else 2):.15g}")
|
|
110
|
+
for v in wm if np.isfinite(v))
|
|
111
|
+
sep = " " if with_sum else " "
|
|
105
112
|
hdr = " " * max_c1 + "".join(str(c).rjust(w)
|
|
106
113
|
for c, w in zip(t.columns, widths))
|
|
107
|
-
lines = [title, "", hdr +
|
|
114
|
+
lines = [title, "", hdr + sep + "Mean".rjust(mx + 1)]
|
|
108
115
|
for r in t.index:
|
|
109
116
|
ln = (" " + str(r)).rjust(max_c1) + "".join(
|
|
110
117
|
f"{v:.0f}".rjust(w) for v, w in zip(t.loc[r], widths))
|
|
111
|
-
lines.append(ln +
|
|
118
|
+
lines.append(ln + sep + f"{wm[r]:.3f}".rjust(mx + 1))
|
|
112
119
|
if not numeric:
|
|
113
120
|
lines += ["", "Computation of the mean based on coding "
|
|
114
121
|
"response categories from 1 to "
|
|
@@ -120,9 +127,11 @@ def bc_items_plotly(frq, order, fill, labels="%", labels_size=None,
|
|
|
120
127
|
labels_cut=0.04, stack100=False, x_lab="",
|
|
121
128
|
y_lab="", legend_title="Responses", main=None,
|
|
122
129
|
digits_d=0, axis_fmt="K", axis_x_pre="",
|
|
123
|
-
rotate_x=0, rotate_y=0,
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
rotate_x=0, rotate_y=0, horiz=True,
|
|
131
|
+
style_opts=None):
|
|
132
|
+
"""One bar per item, stacked by response. frq: responses x items
|
|
133
|
+
counts; order: the items bottom to top, or left to right when
|
|
134
|
+
horiz=False (the vertical chart)."""
|
|
126
135
|
if style_opts is None:
|
|
127
136
|
style_opts = plotly_style()
|
|
128
137
|
cnt = frq[order].to_numpy(dtype=float)
|
|
@@ -147,7 +156,9 @@ def bc_items_plotly(frq, order, fill, labels="%", labels_size=None,
|
|
|
147
156
|
f"{c:.0f}")
|
|
148
157
|
for s, c in zip(share[i], cnt[i])]
|
|
149
158
|
fig.add_trace(go.Bar(
|
|
150
|
-
x=mat[i]
|
|
159
|
+
x=mat[i] if horiz else list(order),
|
|
160
|
+
y=list(order) if horiz else mat[i],
|
|
161
|
+
orientation="h" if horiz else "v", name=str(r),
|
|
151
162
|
marker=dict(color=fills[i % len(fills)],
|
|
152
163
|
line=dict(width=0)),
|
|
153
164
|
text=txt, textposition="inside",
|
|
@@ -155,7 +166,8 @@ def bc_items_plotly(frq, order, fill, labels="%", labels_size=None,
|
|
|
155
166
|
textfont=dict(size=txt_size,
|
|
156
167
|
color=txt_cols[i % len(txt_cols)]),
|
|
157
168
|
customdata=np.stack([cnt[i], share[i]], axis=-1),
|
|
158
|
-
hovertemplate=(
|
|
169
|
+
hovertemplate=(("%{y}" if horiz else "%{x}")
|
|
170
|
+
+ f"<br>{legend_title}: {r}"
|
|
159
171
|
"<br>Count: %{customdata[0]:.0f}"
|
|
160
172
|
"<br>% of item: %{customdata[1]:.1%}"
|
|
161
173
|
"<extra></extra>"),
|
|
@@ -167,11 +179,12 @@ def bc_items_plotly(frq, order, fill, labels="%", labels_size=None,
|
|
|
167
179
|
d = 2
|
|
168
180
|
else:
|
|
169
181
|
d = digits_d
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
val_ax = axis_num(x_lab if horiz else y_lab, axT,
|
|
183
|
+
axis_format(axT, d, axis_fmt, axis_x_pre))
|
|
184
|
+
val_ax.update(range=[0, axT[-1] * (1 if stack100 else 1.02)])
|
|
185
|
+
cat_ax = axis_cat(y_lab if horiz else x_lab)
|
|
186
|
+
cat_ax.update(categoryorder="array", categoryarray=list(order))
|
|
187
|
+
x_ax, y_ax = (val_ax, cat_ax) if horiz else (cat_ax, val_ax)
|
|
175
188
|
if rotate_x:
|
|
176
189
|
x_ax["tickangle"] = -rotate_x
|
|
177
190
|
if rotate_y:
|
|
@@ -181,7 +194,7 @@ def bc_items_plotly(frq, order, fill, labels="%", labels_size=None,
|
|
|
181
194
|
fig.update_layout(
|
|
182
195
|
barmode="stack", bargap=0.2,
|
|
183
196
|
xaxis=x_ax, yaxis=y_ax,
|
|
184
|
-
shapes=x_grid(axT) + plot_border(),
|
|
197
|
+
shapes=(x_grid(axT) if horiz else y_grid(axT)) + plot_border(),
|
|
185
198
|
legend=leg, template=None,
|
|
186
199
|
plot_bgcolor=to_hex(style_opts["panel_fill"]),
|
|
187
200
|
paper_bgcolor=to_hex(style_opts["window_fill"]),
|
lessPy/bc_plotly.py
CHANGED
|
@@ -506,7 +506,7 @@ def bc_facet_plotly(x, x_name=None, facet_name=None,
|
|
|
506
506
|
n_col=1, axis_fmt="K", axis_x_pre="",
|
|
507
507
|
rotate_x=0, rotate_y=0,
|
|
508
508
|
by_tbls=None, by_name=None, beside=False,
|
|
509
|
-
val_name=None, legend_title=None,
|
|
509
|
+
val_name=None, legend_title=None, horiz=True,
|
|
510
510
|
style_opts=None):
|
|
511
511
|
"""Faceted bar chart: one panel per facet level, on a shared
|
|
512
512
|
value axis with horizontal bars, as in the lattice Trellis bar
|
|
@@ -586,7 +586,8 @@ def bc_facet_plotly(x, x_name=None, facet_name=None,
|
|
|
586
586
|
f"<br>{facet_name}: {lv}")
|
|
587
587
|
for cc, v in zip(cats, row)]
|
|
588
588
|
fig.add_trace(go.Bar(
|
|
589
|
-
x=row, y=cats
|
|
589
|
+
x=row if horiz else cats, y=cats if horiz else row,
|
|
590
|
+
orientation="h" if horiz else "v",
|
|
590
591
|
marker=dict(color=fill_vec, opacity=alpha_fill,
|
|
591
592
|
line=dict(color=border_vec, width=1)),
|
|
592
593
|
hoverinfo="text", hovertext=hover,
|
|
@@ -604,24 +605,39 @@ def bc_facet_plotly(x, x_name=None, facet_name=None,
|
|
|
604
605
|
f"<br>{facet_name}: {lv}")
|
|
605
606
|
for cc, v in zip(cats, vals)]
|
|
606
607
|
fig.add_trace(go.Bar(
|
|
607
|
-
x=vals, y=cats
|
|
608
|
+
x=vals if horiz else cats, y=cats if horiz else vals,
|
|
609
|
+
orientation="h" if horiz else "v", name=b,
|
|
608
610
|
legendgroup=b, showlegend=(i == 0),
|
|
609
611
|
marker=dict(color=clr, opacity=alpha_fill,
|
|
610
612
|
line=dict(color=brd, width=1)),
|
|
611
613
|
hoverinfo="text", hovertext=hover,
|
|
612
614
|
), row=r, col=c)
|
|
613
615
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
+
if horiz:
|
|
617
|
+
finish_facet(fig, fac_levels, ax, x_lab, y_lab, gridT1=axT1,
|
|
618
|
+
style_opts=style_opts, y_cat=cats, n_col=n_col)
|
|
619
|
+
else:
|
|
620
|
+
# the vertical chart: categories along x, the shared value
|
|
621
|
+
# scale up the side of every panel
|
|
622
|
+
finish_facet(fig, fac_levels,
|
|
623
|
+
{"axT2": axT1, "axL2": ax["axL1"]},
|
|
624
|
+
y_lab, x_lab, gridT1=None, style_opts=style_opts,
|
|
625
|
+
n_col=n_col, x_cat=cats)
|
|
616
626
|
if grouped:
|
|
617
627
|
fig.update_layout(
|
|
618
628
|
barmode="group" if beside else "stack",
|
|
619
629
|
showlegend=True,
|
|
620
630
|
legend=dict(title=dict(text=(legend_title
|
|
621
631
|
if legend_title is not None
|
|
622
|
-
else by_name)
|
|
632
|
+
else by_name),
|
|
633
|
+
font=dict(color=to_hex(
|
|
634
|
+
style_opts["lab_color"]))),
|
|
635
|
+
font=dict(color=to_hex(style_opts["lab_color"])),
|
|
623
636
|
traceorder="normal"))
|
|
624
|
-
|
|
637
|
+
if horiz:
|
|
638
|
+
fig.update_xaxes(range=[axT1[0], axT1[-1]]) # includes zero
|
|
639
|
+
else:
|
|
640
|
+
fig.update_yaxes(range=[axT1[0], axT1[-1]])
|
|
625
641
|
if rotate_x:
|
|
626
642
|
fig.update_xaxes(tickangle=-rotate_x)
|
|
627
643
|
if rotate_y:
|
lessPy/bubble_plotly.py
CHANGED
|
@@ -63,6 +63,7 @@ def bubble_plotly(x=None, x_name=None, y_name=None, by_name=None,
|
|
|
63
63
|
labels_decimals=None,
|
|
64
64
|
label_min_px=26, label_autocontrast=True,
|
|
65
65
|
facet_tbls=None, facet_name=None, n_col=None,
|
|
66
|
+
shares=False, label_min_value=None,
|
|
66
67
|
style_opts=None):
|
|
67
68
|
|
|
68
69
|
if labels is None:
|
|
@@ -98,8 +99,11 @@ def bubble_plotly(x=None, x_name=None, y_name=None, by_name=None,
|
|
|
98
99
|
|
|
99
100
|
# "prop" plots proportions, which digits_d (0 for counts)
|
|
100
101
|
# would flatten to "0"
|
|
102
|
+
# a percentage of a proportion reads in whole numbers, as the
|
|
103
|
+
# percentages of counts do
|
|
101
104
|
lbl_d = (int(labels_decimals) if labels_decimals is not None
|
|
102
105
|
else (2 if labels == "prop"
|
|
106
|
+
else 0 if (shares and labels == "%")
|
|
103
107
|
else max(0, int(digits_d))))
|
|
104
108
|
trace_mode = "markers" if labels == "off" else "markers+text"
|
|
105
109
|
# None = the default (R's labels_position %||% "in")
|
|
@@ -377,6 +381,11 @@ def bubble_plotly(x=None, x_name=None, y_name=None, by_name=None,
|
|
|
377
381
|
|
|
378
382
|
total = np.nansum(mat)
|
|
379
383
|
share_tot = mat / total if total > 0 else np.zeros(mat.shape)
|
|
384
|
+
# values that are already proportions, each by group's distribution
|
|
385
|
+
# over x, are their own percentages: a share of the table total
|
|
386
|
+
# would divide them again by the number of groups
|
|
387
|
+
if shares:
|
|
388
|
+
share_tot = np.nan_to_num(mat)
|
|
380
389
|
col_tot = np.nansum(mat, axis=0)
|
|
381
390
|
with np.errstate(invalid="ignore", divide="ignore"):
|
|
382
391
|
share_x = np.where(col_tot > 0, mat / col_tot, 0.0)
|
|
@@ -407,8 +416,14 @@ def bubble_plotly(x=None, x_name=None, y_name=None, by_name=None,
|
|
|
407
416
|
else:
|
|
408
417
|
txt = _label_text(row, share_tot[i], labels, digits_d,
|
|
409
418
|
lbl_d)
|
|
410
|
-
|
|
411
|
-
|
|
419
|
+
# a bubble labels its value when it is large enough to hold
|
|
420
|
+
# it; label_min_value states that as a value instead, as
|
|
421
|
+
# R's bubble plot frequency matrix does (power/2.5 * max)
|
|
422
|
+
label_show = ([t if np.isfinite(v) and v > label_min_value
|
|
423
|
+
else "" for t, v in zip(txt, row)]
|
|
424
|
+
if label_min_value is not None else
|
|
425
|
+
[t if np.isfinite(dp) and dp >= label_min_px
|
|
426
|
+
else "" for t, dp in zip(txt, diam_px)])
|
|
412
427
|
customdata = [dict(xcat=c, bycat=g, pct_x=float(px),
|
|
413
428
|
pct_tot=float(pt))
|
|
414
429
|
for c, px, pt in zip(cats, share_x[i],
|
lessPy/corCFA.py
CHANGED
|
@@ -19,7 +19,7 @@ import re
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
import pandas as pd
|
|
21
21
|
|
|
22
|
-
from .utils import fmt, get_option
|
|
22
|
+
from .utils import fmt, get_option, show_plots
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _mimm(R, cuts, NItems, NF, Iter):
|
|
@@ -203,10 +203,10 @@ def corCFA(R, model=None, factors=None, min_cor=0.10,
|
|
|
203
203
|
plots = {}
|
|
204
204
|
if heat_map:
|
|
205
205
|
plots["heatmap"] = _cfa_heatmap(Rout, items, fcols)
|
|
206
|
-
return corCFAResults(
|
|
206
|
+
return show_plots(corCFAResults(
|
|
207
207
|
if_cor=if_cor, ff_cor=ff_cor, communalities=commun,
|
|
208
208
|
alpha=alpha, omega=omega, pred=pred, resid=res,
|
|
209
|
-
plots=plots)
|
|
209
|
+
plots=plots))
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
def _cfa_text(items, fcols, cuts, alpha, omega, iter, if_cor,
|
lessPy/corProp.py
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
import pandas as pd
|
|
13
13
|
|
|
14
|
-
from .utils import get_option
|
|
14
|
+
from .utils import get_option, show_plots
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def corProp(R, main=None, heat_map=True):
|
|
@@ -48,7 +48,7 @@ def corProp(R, main=None, heat_map=True):
|
|
|
48
48
|
if heat_map:
|
|
49
49
|
plots["heatmap"] = _heatmap(out, main)
|
|
50
50
|
out.attrs["plots"] = plots
|
|
51
|
-
return out
|
|
51
|
+
return show_plots(out)
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def _heatmap(df, main):
|
lessPy/corReflect.py
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
import pandas as pd
|
|
13
13
|
|
|
14
|
-
from .utils import get_option
|
|
14
|
+
from .utils import get_option, show_plots
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def corReflect(R, vars, main=None, heat_map=True):
|
|
@@ -47,7 +47,7 @@ def corReflect(R, vars, main=None, heat_map=True):
|
|
|
47
47
|
if heat_map:
|
|
48
48
|
plots["heatmap"] = _heatmap(out, main)
|
|
49
49
|
out.attrs["plots"] = plots
|
|
50
|
-
return out
|
|
50
|
+
return show_plots(out)
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def _heatmap(df, main):
|
lessPy/corReorder.py
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
import pandas as pd
|
|
13
13
|
|
|
14
|
-
from .utils import get_option
|
|
14
|
+
from .utils import get_option, show_plots
|
|
15
15
|
|
|
16
16
|
# R hclust method -> scipy linkage method. scipy 'ward' is R's
|
|
17
17
|
# ward.D2 (squared updates); ward.D has no scipy equivalent, so
|
|
@@ -70,7 +70,7 @@ def corReorder(R, order="hclust", hclust_type="complete",
|
|
|
70
70
|
pass
|
|
71
71
|
out.attrs["plots"] = plots
|
|
72
72
|
out.attrs["order"] = label
|
|
73
|
-
return out
|
|
73
|
+
return show_plots(out)
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
def _chain(S, nv, first):
|
lessPy/corScree.py
CHANGED
|
@@ -11,7 +11,7 @@ import pandas as pd
|
|
|
11
11
|
from .plotly_utils import (
|
|
12
12
|
axis_format, axis_num, plot_border, plotly_style, to_hex,
|
|
13
13
|
x_grid)
|
|
14
|
-
from .utils import fmt, get_option, pretty
|
|
14
|
+
from .utils import fmt, get_option, pretty, show_plots
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class corScreeResults:
|
|
@@ -54,8 +54,8 @@ def corScree(R, main=None):
|
|
|
54
54
|
"differences": _scree_plot(
|
|
55
55
|
ev_diff, "Differences of Successive Eigenvalues",
|
|
56
56
|
main)}
|
|
57
|
-
return corScreeResults(eigenvalues=ev, differences=ev_diff,
|
|
58
|
-
plots=plots)
|
|
57
|
+
return show_plots(corScreeResults(eigenvalues=ev, differences=ev_diff,
|
|
58
|
+
plots=plots))
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def _scree_plot(y, y_lab, main):
|