experiments: support column ordering & sorting in dvc exp show (#4503)

* experiments: preserve --include-... column ordering

* experiments: add --sort-by and --sort-order for exp show

* remove for-else
This commit is contained in:
Peter Rowlands (변기호)
2020-08-31 23:17:58 +09:00
committed by GitHub
parent 54402f3de5
commit 4f8432886d
+57 -10
View File
@@ -29,10 +29,10 @@ def _filter_names(
f" --exclude-{label}"
)
names = {tuple(name.split(".")) for name in names}
names = [tuple(name.split(".")) for name in names]
def _filter(filters, update_func):
filters = {tuple(name.split(".")) for name in filters}
filters = [tuple(name.split(".")) for name in filters]
for length, groups in groupby(filters, len):
for group in groups:
matches = [name for name in names if name[:length] == group]
@@ -41,18 +41,18 @@ def _filter_names(
raise InvalidArgumentError(
f"'{name}' does not match any known {label}"
)
update_func(matches)
update_func({match: None for match in matches})
if include:
ret = set()
ret = OrderedDict()
_filter(include, ret.update)
else:
ret = set(names)
ret = OrderedDict({name: None for name in names})
if exclude:
_filter(exclude, ret.difference_update)
return {".".join(name) for name in ret}
return [".".join(name) for name in ret]
def _update_names(names, items):
@@ -61,7 +61,7 @@ def _update_names(names, items):
item = flatten(item)
names.update(item.keys())
else:
names.add(name)
names[name] = None
def _collect_names(all_experiments, **kwargs):
@@ -74,19 +74,19 @@ def _collect_names(all_experiments, **kwargs):
_update_names(param_names, exp.get("params", {}).items())
metric_names = _filter_names(
metric_names,
sorted(metric_names),
"metrics",
kwargs.get("include_metrics"),
kwargs.get("exclude_metrics"),
)
param_names = _filter_names(
param_names,
sorted(param_names),
"params",
kwargs.get("include_params"),
kwargs.get("exclude_params"),
)
return sorted(metric_names), sorted(param_names)
return metric_names, param_names
def _collect_rows(
@@ -96,7 +96,19 @@ def _collect_rows(
param_names,
precision=DEFAULT_PRECISION,
no_timestamp=False,
sort_by=None,
sort_order=None,
):
if sort_by:
if sort_by in metric_names:
sort_type = "metrics"
elif sort_by in param_names:
sort_type = "params"
else:
raise InvalidArgumentError(f"Unknown sort column '{sort_by}'")
reverse = sort_order == "desc"
experiments = _sort_exp(experiments, sort_by, sort_type, reverse)
for i, (rev, exp) in enumerate(experiments.items()):
row = []
style = None
@@ -122,6 +134,28 @@ def _collect_rows(
yield row, style
def _sort_exp(experiments, sort_by, typ, reverse):
if "baseline" in experiments:
ret = OrderedDict({"baseline": experiments.pop("baseline")})
else:
ret = OrderedDict()
def _sort(item):
_, exp = item
for fname, item in exp.get(typ, {}).items():
if isinstance(item, dict):
item = flatten(item)
else:
item = {fname: item}
if sort_by in item:
val = item[sort_by]
return (val is None, val)
return (True, None)
ret.update(sorted(experiments.items(), key=_sort, reverse=reverse))
return ret
def _format_time(timestamp):
if timestamp is None:
return "-"
@@ -241,6 +275,8 @@ class CmdExperimentsShow(CmdBase):
include_params=self.args.include_params,
exclude_params=self.args.exclude_params,
no_timestamp=self.args.no_timestamp,
sort_by=self.args.sort_by,
sort_order=self.args.sort_order,
)
if not self.args.no_pager:
@@ -418,6 +454,17 @@ def add_parser(subparsers, parent_parser):
help="Exclude the specified params from output table.",
metavar="<params_list>",
)
experiments_show_parser.add_argument(
"--sort-by",
help="Sort related experiments by the specified metric or param.",
metavar="<metric/param>",
)
experiments_show_parser.add_argument(
"--sort-order",
help="Sort order to use with --sort-by.",
choices=("asc", "desc"),
default="asc",
)
experiments_show_parser.add_argument(
"--no-timestamp",
action="store_true",