Repository: biolab/orange3

Issue:
Remove FDR from 'Correlations' output of Correlations (or include p-values)
<!-- 
Thanks for taking the time to submit a feature request!
For the best chance at our team considering your request, please answer the following questions to the best of your ability.
-->

**What's your use case?**
The output of Correlations produces a column _Correlation_ and a column _FDR_ (false discovery rate). The FDR is generally used to correct the α level for p-values in multiple-hypothesis testing (as is, for instance, explained [here](https://towardsdatascience.com/multiple-hypothesis-testing-correction-for-data-scientist-46d3a3d1611d)). There doesn't seem to be any use of an FDR if there is no p-value (correct me if I'm wrong). Since providing p-values appears to be [against the philosophy of Orange](https://orangedatamining.com/blog/2019/1/4/how-to-abuse-p-values-in-correlations/), it doesn't make sense to provide FDRs either: it just creates confusion (it's left me puzzled for some time now)
Alternatively, Orange could of course depart from its philosophy, as it has already done in the Word Enrichment widget in the Text Mining add-on, which provides the p-value alongside the FDR

**What's your proposed solution?**
Remove FDR from the 'Correlations' output of Correlations, or, alternatively `<blasphemy>` also include the p-value `</blasphemy>`

**Are there any alternative solutions?**
- Just ignore the FDR, even if it's there
- Look up the p-value anyway, using an online tool or something like SPSS







Discussion:
You know us too well. Thanks for the blasphemy tag. :)

After some discussion, we decided to add what-must-not-be-named. Say in a column that will be too narrow to be visible and in the moment that the user expands it, the widget will begin showing all kinds of flashy warnings. :)

Seriously, we'll add it, but indeed include an info about why one must be careful with it.

Resolving patch:
diff --git a/Orange/widgets/data/owcorrelations.py b/Orange/widgets/data/owcorrelations.py
--- a/Orange/widgets/data/owcorrelations.py
+++ b/Orange/widgets/data/owcorrelations.py
@@ -393,18 +393,24 @@ def commit(self):
             self.Outputs.correlations.send(None)
             return
 
-        attrs = [ContinuousVariable("Correlation"), ContinuousVariable("FDR")]
+        attrs = [ContinuousVariable("Correlation"),
+                 ContinuousVariable("uncorrected p"),
+                 ContinuousVariable("FDR")]
         metas = [StringVariable("Feature 1"), StringVariable("Feature 2")]
         domain = Domain(attrs, metas=metas)
         model = self.vizrank.rank_model
-        x = np.array([[float(model.data(model.index(row, 0), role))
-                       for role in (Qt.DisplayRole, CorrelationRank.PValRole)]
-                      for row in range(model.rowCount())])
-        x[:, 1] = FDR(list(x[:, 1]))
+        count = model.rowCount()
+        index = model.index
+        corr = np.array([float(index(row, 0).data())
+                         for row in range(count)])
+        p = np.array([index(row, 0).data(CorrelationRank.PValRole)
+                      for row in range(count)])
+        fdr = FDR(p)
+        x = np.vstack((corr, p, fdr)).T
         # pylint: disable=protected-access
-        m = np.array([[a.name for a in model.data(model.index(row, 0),
-                                                  CorrelationRank._AttrRole)]
-                      for row in range(model.rowCount())], dtype=object)
+        m = np.array([[a.name
+                       for a in index(row, 0).data(CorrelationRank._AttrRole)]
+                      for row in range(count)], dtype=object)
         corr_table = Table(domain, x, metas=m)
         corr_table.name = "Correlations"
 


Test patch:
diff --git a/Orange/widgets/data/tests/test_owcorrelations.py b/Orange/widgets/data/tests/test_owcorrelations.py
--- a/Orange/widgets/data/tests/test_owcorrelations.py
+++ b/Orange/widgets/data/tests/test_owcorrelations.py
@@ -158,10 +158,14 @@ def test_output_correlations(self):
         self.assertIsInstance(correlations, Table)
         self.assertEqual(len(correlations), 6)
         self.assertEqual(len(correlations.domain.metas), 2)
-        self.assertListEqual(["Correlation", "FDR"],
+        self.assertListEqual(["Correlation", "uncorrected p", "FDR"],
                              [m.name for m in correlations.domain.attributes])
-        array = np.array([[0.963, 0], [0.872, 0], [0.818, 0], [-0.421, 0],
-                          [-0.357, 0.000009], [-0.109, 0.1827652]])
+        array = np.array([[0.963, 0, 0],
+                          [0.872, 0, 0],
+                          [0.818, 0, 0],
+                          [-0.421, 0, 0],
+                          [-0.357, 7.52e-6, 0.000009],
+                          [-0.109, 0.1827652, 0.1827652]])
         npt.assert_almost_equal(correlations.X, array)
 
     def test_input_changed(self):