Repository: biolab/orange3

Issue:
File widget: change attribute type from nominal to numeric
##### Orange version
3.4.4.

##### Expected behavior
If attribute type change from nominal to numeric, the number values shall remain the same. E.g. if there were two nominal values 1 and 2, the same two values should remain after the attribute type change.

##### Actual behavior
If attribute type change from nominal to numeric, the number representation change. E.g. if there were two nominal values 1 and 2, after the attribute type change we have 0 and 1. This happens only if values are 1 and 2, if the values are 22 and 33 (or other) this does not happen.

##### Steps to reproduce the behavior
open attached data sheet (test.xlsx) with file widget
change attribute type for '2nd-code' from nominal to numeric
see '2nd-code' values in the data table widget


##### Additional info (worksheets, data, screenshots, ...)
data file

[test.xlsx](https://github.com/biolab/orange3/files/1095164/test.xlsx)

before attribute type change

![one](https://user-images.githubusercontent.com/11367976/27440205-505fe4fc-576a-11e7-96bd-bdb9c872e391.png)

after attribute type change

![nominal-numeric](https://user-images.githubusercontent.com/11367976/27440216-5952c048-576a-11e7-965e-9536b97517af.png)






Discussion:

Resolving patch:
diff --git a/Orange/widgets/utils/domaineditor.py b/Orange/widgets/utils/domaineditor.py
--- a/Orange/widgets/utils/domaineditor.py
+++ b/Orange/widgets/utils/domaineditor.py
@@ -248,7 +248,7 @@ def get_domain(self, domain, data):
         places = [[], [], []]  # attributes, class_vars, metas
         cols = [[], [], []]  # Xcols, Ycols, Mcols
 
-        for (name, tpe, place, _, _), (orig_var, orig_plc) in \
+        for (name, tpe, place, _, may_be_numeric), (orig_var, orig_plc) in \
                 zip(variables,
                         chain([(at, Place.feature) for at in domain.attributes],
                               [(cl, Place.class_var) for cl in domain.class_vars],
@@ -261,8 +261,6 @@ def get_domain(self, domain, data):
 
             cont_ints = type(orig_var) == ContinuousVariable and \
                         all(x.is_integer() for x in self._iter_vals(col_data) if not np.isnan(x))
-            disc_ints = type(orig_var) == DiscreteVariable and \
-                        all(x.isdecimal() for x in orig_var.values)
 
             if name == orig_var.name and tpe == type(orig_var):
                 var = orig_var
@@ -292,7 +290,7 @@ def get_domain(self, domain, data):
                 col_data = self._to_column(col_data, False, dtype=object)
             elif tpe == ContinuousVariable and type(orig_var) == DiscreteVariable:
                 var = tpe(name)
-                if disc_ints:
+                if may_be_numeric:
                     col_data = [np.nan if self._is_missing(x) else float(orig_var.values[int(x)])
                                 for x in self._iter_vals(col_data)]
                 col_data = self._to_column(col_data, is_sparse)


Test patch:
diff --git a/Orange/widgets/data/tests/test_owfile.py b/Orange/widgets/data/tests/test_owfile.py
--- a/Orange/widgets/data/tests/test_owfile.py
+++ b/Orange/widgets/data/tests/test_owfile.py
@@ -247,13 +247,13 @@ def test_add_new_format(self):
         self.assertTrue(".123" in formats)
 
     def test_domain_editor_conversions(self):
-        dat = """V0\tV1\tV2\tV3\tV4\tV5
-                 c\tc\td\td\tc\td
-                  \t \t \t \t \t
-                 3.0\t1.0\t4\ta\t0.0\tx
-                 1.0\t2.0\t4\tb\t0.0\ty
-                 2.0\t1.0\t7\ta\t0.0\ty
-                 0.0\t2.0\t7\ta\t0.0\tz"""
+        dat = """V0\tV1\tV2\tV3\tV4\tV5\tV6
+                 c\tc\td\td\tc\td\td
+                  \t \t \t \t \t \t
+                 3.0\t1.0\t4\ta\t0.0\tx\t1.0
+                 1.0\t2.0\t4\tb\t0.0\ty\t2.0
+                 2.0\t1.0\t7\ta\t0.0\ty\t2.0
+                 0.0\t2.0\t7\ta\t0.0\tz\t2.0"""
         with named_file(dat, suffix=".tab") as filename:
             self.open_dataset(filename)
             data1 = self.get_output(self.widget.Outputs.data)
@@ -266,6 +266,7 @@ def test_domain_editor_conversions(self):
             model.setData(model.createIndex(1, 1), "string", Qt.EditRole)
             model.setData(model.createIndex(2, 1), "numeric", Qt.EditRole)
             model.setData(model.createIndex(3, 1), "numeric", Qt.EditRole)
+            model.setData(model.createIndex(6, 1), "numeric", Qt.EditRole)
             self.widget.apply_button.click()
             data2 = self.get_output(self.widget.Outputs.data)
             # round continuous values should be converted to integers (3.0 -> 3, "3")
@@ -273,6 +274,8 @@ def test_domain_editor_conversions(self):
             self.assertEqual(len(data2[0].metas[0]), 1)
             # discrete integer values should stay the same after conversion to continuous
             self.assertAlmostEqual(float(data1[0][2].value), data2[0][1])
+            # discrete round floats should stay the same after conversion to continuous
+            self.assertAlmostEqual(float(data1[0][6].value), data2[0][5])
 
     def test_url_no_scheme(self):
         mock_urlreader = Mock(side_effect=ValueError())