From 26c64992e6c9d310b809b03bbb1ef9c5ed40dbe2 Mon Sep 17 00:00:00 2001 From: BlazZupan Date: Sun, 5 Aug 2018 16:10:40 +0200 Subject: [PATCH 1/8] Display data set name --- Orange/widgets/data/owdatainfo.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index ad963273ebf..481bdb298d0 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -34,10 +34,11 @@ def __init__(self): super().__init__() self.data(None) + self.data_set_name = "N/A" self.data_set_size = self.features = self.meta_attributes = "" self.location = "" - for box in ("Data Set Size", "Features", "Targets", "Meta Attributes", - "Location", "Data Attributes"): + for box in ("Data Set Name", "Data Set Size", "Features", "Targets", + "Meta Attributes", "Location", "Data Attributes"): name = box.lower().replace(" ", "_") bo = gui.vBox(self.controlArea, box, addSpace=False and box != "Meta Attributes") @@ -73,6 +74,7 @@ def pack_table(info): ) + "\n" if data is None: + self.data_set_name = "N/A" self.data_set_size = "No data" self.features = self.targets = self.meta_attributes = "None" self.location = "" @@ -99,6 +101,11 @@ def update_size(): threading.Thread(target=update_size).start() + if hasattr(data, "name"): + self.data_set_name = data.name + else: + self.data_set_name = "N/A" + if not domain.attributes: self.features = "None" else: From 0821a14bfe32bff62ec06a942f3567981d82bfef Mon Sep 17 00:00:00 2001 From: BlazZupan Date: Sun, 5 Aug 2018 16:11:14 +0200 Subject: [PATCH 2/8] Display None when no target features --- Orange/widgets/data/owdatainfo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 481bdb298d0..2ac5419027d 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -54,7 +54,7 @@ def __init__(self): self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width()) self.layout().setSizeConstraint(QtWidgets.QLayout.SetFixedSize) - self.targets = "" + self.targets = "None" self.data_attributes = "" self.data_desc = None @@ -146,6 +146,8 @@ def update_size(): else: self.targets = "

Multi-target data

\n" + pack_table( (("Categorical", disc_class), ("Numeric", cont_class))) + else: + self.targets = "None" self.data_desc = dd = OrderedDict() From c4607086a427f924f4d372aa369767a6567ad4d2 Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 22:43:59 +0200 Subject: [PATCH 3/8] Data Info: Rename discrete to categorical --- Orange/widgets/data/owdatainfo.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 2ac5419027d..c624013a090 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -45,7 +45,7 @@ def __init__(self): gui.label(bo, self, "%%(%s)s" % name) # ensure the widget has some decent minimum width. - self.targets = "Discrete outcome with 123 values" + self.targets = "Categorical outcome with 123 values" self.layout().activate() # NOTE: The minimum width is set on the 'contained' widget and # not `self`. The layout will set a fixed size to `self` taking @@ -112,7 +112,7 @@ def update_size(): disc_features = count(domain.attributes, DiscreteVariable) cont_features = count(domain.attributes, ContinuousVariable) self.features = pack_table(( - ("Discrete", n_or_none(disc_features)), + ("Categorical", n_or_none(disc_features)), ("Numeric", n_or_none(cont_features)) )) @@ -123,7 +123,7 @@ def update_size(): cont_metas = count(domain.metas, ContinuousVariable) str_metas = count(domain.metas, StringVariable) self.meta_attributes = pack_table(( - ("Discrete", n_or_none(disc_metas)), + ("Categorical", n_or_none(disc_metas)), ("Numeric", n_or_none(cont_metas)), ("Textual", n_or_none(str_metas)))) @@ -132,7 +132,7 @@ def update_size(): if class_var.is_continuous: self.targets = "Numeric target variable" else: - self.targets = "Discrete outcome with %i values" % \ + self.targets = "Categorical outcome with %i values" % \ len(class_var.values) elif domain.class_vars: disc_class = count(domain.class_vars, DiscreteVariable) From eac0d37432bde07eb7b65db9e8d0a1e7d3daaeec Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 22:44:25 +0200 Subject: [PATCH 4/8] Data Info: Refactor getting data set name --- Orange/widgets/data/owdatainfo.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index c624013a090..76dbc1e2c17 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -101,10 +101,7 @@ def update_size(): threading.Thread(target=update_size).start() - if hasattr(data, "name"): - self.data_set_name = data.name - else: - self.data_set_name = "N/A" + self.data_set_name = getattr(data, "name", "N/A") if not domain.attributes: self.features = "None" From 8168727f206fb2edbb5135a132a97aa97e64837c Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 22:44:41 +0200 Subject: [PATCH 5/8] Data Info: Add data set name to report --- Orange/widgets/data/owdatainfo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 76dbc1e2c17..0d35313cfa1 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -147,6 +147,7 @@ def update_size(): self.targets = "None" self.data_desc = dd = OrderedDict() + dd["Name"] = self.data_set_name if SqlTable is not None and isinstance(data, SqlTable): connection_string = ' '.join( From e234f5fdf19bfb158527e4facf76c97d704dd8a6 Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 22:51:49 +0200 Subject: [PATCH 6/8] Data Info: Refactor to ensure consistency when no data --- Orange/widgets/data/owdatainfo.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 0d35313cfa1..71e7f2e8a09 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -33,10 +33,8 @@ class Inputs: def __init__(self): super().__init__() - self.data(None) - self.data_set_name = "N/A" - self.data_set_size = self.features = self.meta_attributes = "" - self.location = "" + self.clear_fields() + for box in ("Data Set Name", "Data Set Size", "Features", "Targets", "Meta Attributes", "Location", "Data Attributes"): name = box.lower().replace(" ", "_") @@ -54,9 +52,14 @@ def __init__(self): self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width()) self.layout().setSizeConstraint(QtWidgets.QLayout.SetFixedSize) - self.targets = "None" - self.data_attributes = "" + + def clear_fields(self): + self.data_set_name = "" + self.data_set_size = "" + self.features = self.targets = self.meta_attributes = "" + self.location = "" self.data_desc = None + self.data_attributes = "" @Inputs.data def data(self, data): @@ -74,12 +77,7 @@ def pack_table(info): ) + "\n" if data is None: - self.data_set_name = "N/A" - self.data_set_size = "No data" - self.features = self.targets = self.meta_attributes = "None" - self.location = "" - self.data_desc = None - self.data_attributes = "" + self.clear_fields() return sparseness = [s for s, m in (("features", data.X_density), From 23ec02719db8c21f4aab6fea14e5815f98f95438 Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 23:25:59 +0200 Subject: [PATCH 7/8] Data Info: Refactor into smaller methods --- Orange/widgets/data/owdatainfo.py | 102 ++++++++++++++++-------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 71e7f2e8a09..6e3b7f68460 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -33,7 +33,7 @@ class Inputs: def __init__(self): super().__init__() - self.clear_fields() + self._clear_fields() for box in ("Data Set Name", "Data Set Size", "Features", "Targets", "Meta Attributes", "Location", "Data Attributes"): @@ -49,11 +49,20 @@ def __init__(self): # not `self`. The layout will set a fixed size to `self` taking # into account the minimum constraints of the children (it would # override any minimum/fixed size set on `self`). + self.targets = "" self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width()) self.layout().setSizeConstraint(QtWidgets.QLayout.SetFixedSize) - def clear_fields(self): + @Inputs.data + def data(self, data): + if data is None: + self._clear_fields() + else: + self._set_fields(data) + self._set_report(data) + + def _clear_fields(self): self.data_set_name = "" self.data_set_size = "" self.features = self.targets = self.meta_attributes = "" @@ -61,13 +70,13 @@ def clear_fields(self): self.data_desc = None self.data_attributes = "" - @Inputs.data - def data(self, data): - def n_or_none(i): - return i or "(none)" + @staticmethod + def _count(s, tpe): + return sum(isinstance(x, tpe) for x in s) - def count(s, tpe): - return sum(isinstance(x, tpe) for x in s) + def _set_fields(self, data): + def n_or_none(n): + return n or "none" def pack_table(info): return '\n' + "\n".join( @@ -76,9 +85,19 @@ def pack_table(info): for d, v in info ) + "
\n" - if data is None: - self.clear_fields() - return + def pack_counts(s, include_non_primitive=False): + if not s: + return "None" + return pack_table( + (name, n_or_none(self._count(s, type_))) + for name, type_ in ( + ("Categorical", DiscreteVariable), + ("Numeric", ContinuousVariable), + ("Text", StringVariable))[:2 + include_non_primitive] + ) + + domain = data.domain + class_var = domain.class_var sparseness = [s for s, m in (("features", data.X_density), ("meta attributes", data.metas_density), @@ -87,7 +106,6 @@ def pack_table(info): sparseness = "

Sparse representation: %s

" % ", ".join(sparseness) else: sparseness = "" - domain = data.domain self.data_set_size = pack_table(( ("Rows", '~{}'.format(data.approx_len())), ("Columns", len(domain)+len(domain.metas)))) + sparseness @@ -101,28 +119,8 @@ def update_size(): self.data_set_name = getattr(data, "name", "N/A") - if not domain.attributes: - self.features = "None" - else: - disc_features = count(domain.attributes, DiscreteVariable) - cont_features = count(domain.attributes, ContinuousVariable) - self.features = pack_table(( - ("Categorical", n_or_none(disc_features)), - ("Numeric", n_or_none(cont_features)) - )) - - if not domain.metas: - self.meta_attributes = "None" - else: - disc_metas = count(domain.metas, DiscreteVariable) - cont_metas = count(domain.metas, ContinuousVariable) - str_metas = count(domain.metas, StringVariable) - self.meta_attributes = pack_table(( - ("Categorical", n_or_none(disc_metas)), - ("Numeric", n_or_none(cont_metas)), - ("Textual", n_or_none(str_metas)))) - - class_var = domain.class_var + self.features = pack_counts(domain.attributes) + self.meta_attributes = pack_counts(domain.metas, True) if class_var: if class_var.is_continuous: self.targets = "Numeric target variable" @@ -130,8 +128,8 @@ def update_size(): self.targets = "Categorical outcome with %i values" % \ len(class_var.values) elif domain.class_vars: - disc_class = count(domain.class_vars, DiscreteVariable) - cont_class = count(domain.class_vars, ContinuousVariable) + disc_class = self._count(domain.class_vars, DiscreteVariable) + cont_class = self._count(domain.class_vars, ContinuousVariable) if not cont_class: self.targets = "Multi-target data,\n%i categorical targets" % \ n_or_none(disc_class) @@ -139,11 +137,20 @@ def update_size(): self.targets = "Multi-target data,\n%i numeric targets" % \ n_or_none(cont_class) else: - self.targets = "

Multi-target data

\n" + pack_table( - (("Categorical", disc_class), ("Numeric", cont_class))) + self.targets = "

Multi-target data

\n" + \ + pack_counts(domain.class_vars) else: self.targets = "None" + if data.attributes: + self.data_attributes = pack_table(data.attributes.items()) + else: + self.data_attributes = "" + + def _set_report(self, data): + domain = data.domain + count = self._count + self.data_desc = dd = OrderedDict() dd["Name"] = self.data_set_name @@ -162,9 +169,9 @@ def update_size(): def join_if(items): return ", ".join(s.format(n) for s, n in items if n) - dd["Features"] = len(domain.attributes) and join_if(( - ("{} categorical", disc_features), - ("{} numeric", cont_features) + dd["Features"] = len(domain.attributes) > 0 and join_if(( + ("{} categorical", count(domain.attributes, DiscreteVariable)), + ("{} numeric", count(domain.attributes, ContinuousVariable)) )) if domain.class_var: name = domain.class_var.name @@ -173,22 +180,19 @@ def join_if(items): else: dd["Target"] = "numeric target '{}'".format(name) elif domain.class_vars: + disc_class = count(domain.class_vars, DiscreteVariable) + cont_class = count(domain.class_vars, ContinuousVariable) tt = "" if disc_class: tt += report.plural("{number} categorical outcome{s}", disc_class) if cont_class: tt += report.plural("{number} numeric target{s}", cont_class) dd["Meta attributes"] = len(domain.metas) > 0 and join_if(( - ("{} categorical", disc_metas), - ("{} numeric", cont_metas), - ("{} textual", str_metas) + ("{} categorical", count(domain.metas, DiscreteVariable)), + ("{} numeric", count(domain.metas, ContinuousVariable)), + ("{} text", count(domain.metas, StringVariable)) )) - if data.attributes: - self.data_attributes = pack_table(data.attributes.items()) - else: - self.data_attributes = "" - def send_report(self): if self.data_desc: self.report_items(self.data_desc) From 41c5f3ba198fbd091c371863c521f5e3027a1057 Mon Sep 17 00:00:00 2001 From: janezd Date: Tue, 23 Oct 2018 23:34:52 +0200 Subject: [PATCH 8/8] Data Info: Replace % with format --- Orange/widgets/data/owdatainfo.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Orange/widgets/data/owdatainfo.py b/Orange/widgets/data/owdatainfo.py index 6e3b7f68460..2358b088be0 100644 --- a/Orange/widgets/data/owdatainfo.py +++ b/Orange/widgets/data/owdatainfo.py @@ -76,12 +76,14 @@ def _count(s, tpe): def _set_fields(self, data): def n_or_none(n): - return n or "none" + return n or "-" def pack_table(info): return '\n' + "\n".join( - '\n' - '\n' % (d, textwrap.shorten(str(v), width=30, placeholder="...")) + '\n' + '\n'.format( + d, + textwrap.shorten(str(v), width=30, placeholder="...")) for d, v in info ) + "
%s:%s
{}:{}
\n" @@ -103,7 +105,8 @@ def pack_counts(s, include_non_primitive=False): ("meta attributes", data.metas_density), ("targets", data.Y_density)) if m() > 1] if sparseness: - sparseness = "

Sparse representation: %s

" % ", ".join(sparseness) + sparseness = "

Sparse representation: {}

"\ + .format(", ".join(sparseness)) else: sparseness = "" self.data_set_size = pack_table(( @@ -125,17 +128,17 @@ def update_size(): if class_var.is_continuous: self.targets = "Numeric target variable" else: - self.targets = "Categorical outcome with %i values" % \ - len(class_var.values) + self.targets = "Categorical outcome with {} values"\ + .format(len(class_var.values)) elif domain.class_vars: disc_class = self._count(domain.class_vars, DiscreteVariable) cont_class = self._count(domain.class_vars, ContinuousVariable) if not cont_class: - self.targets = "Multi-target data,\n%i categorical targets" % \ - n_or_none(disc_class) + self.targets = "Multi-target data,\n{} categorical targets"\ + .format(n_or_none(disc_class)) elif not disc_class: - self.targets = "Multi-target data,\n%i numeric targets" % \ - n_or_none(cont_class) + self.targets = "Multi-target data,\n{} numeric targets"\ + .format(n_or_none(cont_class)) else: self.targets = "

Multi-target data

\n" + \ pack_counts(domain.class_vars) @@ -156,11 +159,11 @@ def _set_report(self, data): if SqlTable is not None and isinstance(data, SqlTable): connection_string = ' '.join( - '%s=%s' % (key, value) + '{}={}'.format(key, value) for key, value in data.connection_params.items() if value is not None and key != 'password') - self.location = "Table '%s', using connection:\n%s" % ( - data.table_name, connection_string) + self.location = "Table '{}', using connection:\n{}"\ + .format(data.table_name, connection_string) dd["Rows"] = data.approx_len() else: self.location = "Data is stored in memory"