Skip to content

Commit 5f0ac8b

Browse files
finishing up ECDF
1 parent 807b828 commit 5f0ac8b

File tree

3 files changed

+58
-22
lines changed

3 files changed

+58
-22
lines changed

packages/python/plotly/plotly/express/_chart_types.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ def ecdf(
496496
color=None,
497497
text=None,
498498
line_dash=None,
499+
symbol=None,
499500
facet_row=None,
500501
facet_col=None,
501502
facet_col_wrap=0,
@@ -505,18 +506,22 @@ def ecdf(
505506
hover_data=None,
506507
animation_frame=None,
507508
animation_group=None,
509+
markers=False,
510+
lines=True,
508511
category_orders=None,
509512
labels=None,
510513
color_discrete_sequence=None,
511514
color_discrete_map=None,
512515
line_dash_sequence=None,
513516
line_dash_map=None,
517+
symbol_sequence=None,
518+
symbol_map=None,
514519
marginal=None,
515520
opacity=None,
516521
orientation=None,
517522
line_shape="hv",
518-
norm="probability",
519-
complementary=False,
523+
ecdfnorm="probability",
524+
ecdfmode="standard",
520525
log_x=False,
521526
log_y=False,
522527
range_x=None,
@@ -574,7 +579,7 @@ def kde(
574579
marginal=None,
575580
opacity=None,
576581
orientation=None,
577-
norm=None, # TODO use this
582+
kdenorm=None, # TODO use this
578583
kernel=None, # TODO use this
579584
bw_method=None, # TODO use this
580585
bw_adjust=None, # TODO use this

packages/python/plotly/plotly/express/_core.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,12 @@ def configure_cartesian_axes(args, fig, orders):
660660
if "is_timeline" in args:
661661
fig.update_xaxes(type="date")
662662

663+
if "ecdfmode" in args:
664+
if args["orientation"] == "v":
665+
fig.update_yaxes(rangemode="tozero")
666+
else:
667+
fig.update_xaxes(rangemode="tozero")
668+
663669

664670
def configure_ternary_axes(args, fig, orders):
665671
fig.update_ternaries(
@@ -1313,7 +1319,7 @@ def build_dataframe(args, constructor):
13131319
value_name = None # will likely be "value" in wide_mode
13141320
hist2d_types = [go.Histogram2d, go.Histogram2dContour]
13151321
hist1d_orientation = (
1316-
constructor == go.Histogram or "complementary" in args or "kernel" in args
1322+
constructor == go.Histogram or "ecdfmode" in args or "kernel" in args
13171323
)
13181324
if constructor in cartesians:
13191325
if wide_x and wide_y:
@@ -1802,11 +1808,15 @@ def infer_config(args, constructor, trace_patch, layout_patch):
18021808
if (
18031809
"line_group" in args or "line_dash" in args
18041810
): # px.line, px.line_*, px.area, px.ecdf, px, kde
1805-
modes = set(["lines"])
1811+
modes = set()
1812+
if args.get("lines", True):
1813+
modes.add("lines")
18061814
if args.get("text") or args.get("symbol") or args.get("markers"):
18071815
modes.add("markers")
18081816
if args.get("text"):
18091817
modes.add("text")
1818+
if len(modes) == 0:
1819+
modes.add("lines")
18101820
trace_patch["mode"] = "+".join(modes)
18111821
elif constructor != go.Splom and (
18121822
"symbol" in args or constructor == go.Scattermapbox
@@ -1856,13 +1866,13 @@ def infer_config(args, constructor, trace_patch, layout_patch):
18561866
if "trendline_options" in args and args["trendline_options"] is None:
18571867
args["trendline_options"] = dict()
18581868

1859-
if "norm" in args:
1860-
if args.get("norm", None) not in [None, "percent", "probability"]:
1869+
if "ecdfnorm" in args:
1870+
if args.get("ecdfnorm", None) not in [None, "percent", "probability"]:
18611871
raise ValueError(
1862-
"`norm` must be one of None, 'percent' or 'probability'. "
1863-
+ "'%s' was provided." % args["norm"]
1872+
"`ecdfnorm` must be one of None, 'percent' or 'probability'. "
1873+
+ "'%s' was provided." % args["ecdfnorm"]
18641874
)
1865-
args["histnorm"] = args["norm"]
1875+
args["histnorm"] = args["ecdfnorm"]
18661876

18671877
# Compute applicable grouping attributes
18681878
for k in group_attrables:
@@ -2078,18 +2088,22 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None):
20782088
):
20792089
trace.update(marker=dict(color=trace.line.color))
20802090

2081-
if "complementary" in args: # ECDF
2091+
if "ecdfmode" in args:
20822092
base = args["x"] if args["orientation"] == "v" else args["y"]
20832093
var = args["x"] if args["orientation"] == "h" else args["y"]
2084-
group = group.sort_values(by=base)
2085-
group_sum = group[var].sum()
2094+
ascending = args.get("ecdfmode", "standard") != "reversed"
2095+
group = group.sort_values(by=base, ascending=ascending)
2096+
group_sum = group[var].sum() # compute here before next line mutates
20862097
group[var] = group[var].cumsum()
2087-
if args["complementary"]:
2098+
if not ascending:
2099+
group = group.sort_values(by=base, ascending=True)
2100+
2101+
if args.get("ecdfmode", "standard") == "complementary":
20882102
group[var] = group_sum - group[var]
20892103

2090-
if args["norm"] == "probability":
2104+
if args["ecdfnorm"] == "probability":
20912105
group[var] = group[var] / group_sum
2092-
elif args["norm"] == "percent":
2106+
elif args["ecdfnorm"] == "percent":
20932107
group[var] = 100.0 * group[var] / group_sum
20942108

20952109
patch, fit_results = make_trace_kwargs(

packages/python/plotly/plotly/express/_doc.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,11 @@
325325
"Setting this value is recommended when using `plotly.express.colors.diverging` color scales as the inputs to `color_continuous_scale`.",
326326
],
327327
size_max=["int (default `20`)", "Set the maximum mark size when using `size`."],
328-
markers=["boolean (default `False`)", "If `True`, markers are shown on lines.",],
328+
markers=["boolean (default `False`)", "If `True`, markers are shown on lines."],
329+
lines=[
330+
"boolean (default `True`)",
331+
"If `False`, lines are not drawn (forced to `True` if `markers` is `False`).",
332+
],
329333
log_x=[
330334
"boolean (default `False`)",
331335
"If `True`, the x-axis is log-scaled in cartesian coordinates.",
@@ -573,11 +577,24 @@
573577
"Sets the number of rendered sectors from any given `level`. Set `maxdepth` to -1 to render all the"
574578
"levels in the hierarchy.",
575579
],
576-
norm=["TODO"],
577-
complementary=["TODO"],
578-
kernel=["TODO"],
579-
bw_method=["TODO"],
580-
bw_adjust=["TODO"],
580+
ecdfnorm=[
581+
"string or `None` (default `'probability'`)",
582+
"One of `'probability'` or `'percent'`",
583+
"If `None`, values will be raw counts or sums.",
584+
"If `'probability', values will be probabilities normalized from 0 to 1.",
585+
"If `'percent', values will be percentages normalized from 0 to 100.",
586+
],
587+
ecdfmode=[
588+
"string (default `'standard'`)",
589+
"One of `'standard'`, `'complementary'` or `'reversed'`",
590+
"If `'standard'`, the ECDF is plotted such that values represent data at or below the point.",
591+
"If `'complementary'`, the CCDF is plotted such that values represent data above the point.",
592+
"If `'reversed'`, a variant of the CCDF is plotted such that values represent data at or above the point.",
593+
],
594+
kernel=["TODO"], # kde
595+
kdenorm=["TODO"], # kde
596+
bw_method=["TODO"], # kde
597+
bw_adjust=["TODO"], # kde
581598
)
582599

583600

0 commit comments

Comments
 (0)