Skip to content

Commit 735ced5

Browse files
authored
Merge pull request #3737 from pavlin-policar/kmeans-louvain-array-eq
Replace statistics.util.array_equal with data.util.array_equal
2 parents 302cd74 + 8ca5250 commit 735ced5

File tree

6 files changed

+41
-44
lines changed

6 files changed

+41
-44
lines changed

Orange/statistics/util.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,18 @@
77
import warnings
88
from typing import Iterable
99

10-
import numpy as np
1110
import bottleneck as bn
12-
from scipy import sparse as sp
11+
import numpy as np
1312
import scipy.stats.stats
14-
from sklearn.utils.sparsefuncs import mean_variance_axis
15-
16-
17-
def sparse_array_equal(x1, x2):
18-
"""Check if two sparse arrays are equal."""
19-
if not sp.issparse(x1):
20-
raise TypeError("`x1` must be sparse.")
21-
if not sp.issparse(x2):
22-
raise TypeError("`x2` must be sparse.")
13+
from scipy import sparse as sp
2314

24-
return x1.shape == x2.shape and (x1 != x2).nnz == 0
15+
from sklearn.utils.sparsefuncs import mean_variance_axis
2516

17+
from Orange.data.util import array_equal
18+
from Orange.util import deprecated
2619

27-
def array_equal(x1, x2):
28-
"""Equivalent of np.array_equal that properly handles sparse matrices."""
29-
if sp.issparse(x1) and sp.issparse(x2):
30-
return sparse_array_equal(x1, x2)
31-
return np.array_equal(x1, x2)
20+
# For backwards compatibility
21+
array_equal = deprecated("Orange.data.util.array_equal")(array_equal)
3222

3323

3424
def _count_nans_per_row_sparse(X, weights, dtype=None):

Orange/tests/test_statistics.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import unittest
22
import warnings
3+
from distutils.version import LooseVersion
34
from itertools import chain
45
from functools import partial, wraps
56

67
import numpy as np
78
from scipy.sparse import csr_matrix, issparse, lil_matrix, csc_matrix, \
89
SparseEfficiencyWarning
910

11+
import Orange
1012
from Orange.statistics.util import bincount, countnans, contingency, digitize, \
1113
mean, nanmax, nanmean, nanmedian, nanmin, nansum, nanunique, stats, std, \
12-
unique, var, nanstd, nanvar, nanmode, array_equal, FDR
14+
unique, var, nanstd, nanvar, nanmode, FDR
1315
from sklearn.utils import check_random_state
1416

1517

@@ -34,10 +36,20 @@ def sparse_with_explicit_zero(x, array):
3436

3537
return sp_array
3638

39+
# Make sure to call setUp and tearDown methods in between test runs so
40+
# any widget state doesn't interfere between tests
41+
def _setup_teardown():
42+
self.tearDown()
43+
self.setUp()
44+
3745
test_case(self, np.array)
46+
_setup_teardown()
3847
test_case(self, csr_matrix)
48+
_setup_teardown()
3949
test_case(self, csc_matrix)
50+
_setup_teardown()
4051
test_case(self, partial(sparse_with_explicit_zero, array=csr_matrix))
52+
_setup_teardown()
4153
test_case(self, partial(sparse_with_explicit_zero, array=csc_matrix))
4254

4355
return _wrapper
@@ -295,6 +307,17 @@ def test_FDR_list(self):
295307
np.array([0.00033, 0.0004, 0.00005, 0.00038, 0.00025]),
296308
result, decimal=5)
297309

310+
def test_array_equal_deprecated(self):
311+
"""This test is to be included in the 3.22 release and will fail in
312+
version 3.24. This serves as a reminder to remove the deprecated method
313+
and this test."""
314+
if LooseVersion(Orange.__version__) >= LooseVersion("3.24"):
315+
self.fail(
316+
"`Orange.statistics.util.array_equal` was deprecated in "
317+
"version 3.22, and there have been two minor versions in "
318+
"between. Please remove the deprecated method from the module."
319+
)
320+
298321

299322
class TestNanmean(unittest.TestCase):
300323
def setUp(self):
@@ -622,25 +645,6 @@ def test_nanunique_ignores_nans_in_counts(self, array):
622645
np.testing.assert_equal(nanunique(x, return_counts=True)[1], expected)
623646

624647

625-
class TestArrayEqual(unittest.TestCase):
626-
@dense_sparse
627-
def test_same_matrices(self, array):
628-
x = array([0, 1, 0, 0, 2])
629-
self.assertTrue(array_equal(x, x))
630-
631-
@dense_sparse
632-
def test_with_different_shapes(self, array):
633-
x = array(np.eye(4))
634-
y = array(np.eye(5))
635-
self.assertFalse(array_equal(x, y))
636-
637-
@dense_sparse
638-
def test_with_different_values(self, array):
639-
x = array([0, 1, 0, 0, 2])
640-
y = array([0, 3, 0, 0, 2])
641-
self.assertFalse(array_equal(x, y))
642-
643-
644648
class TestNanModeAppVeyor(unittest.TestCase):
645649
def test_appveyour_still_not_onscipy_1_2_0(self):
646650
import scipy

Orange/widgets/tests/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,11 @@ def table_dense_sparse(test_case):
336336

337337
@wraps(test_case)
338338
def _wrapper(self):
339+
# Make sure to call setUp and tearDown methods in between test runs so
340+
# any widget state doesn't interfere between tests
339341
test_case(self, lambda table: table.to_dense())
342+
self.tearDown()
343+
self.setUp()
340344
test_case(self, lambda table: table.to_sparse())
341345

342346
return _wrapper

Orange/widgets/unsupervised/owkmeans.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from Orange.clustering import KMeans
1111
from Orange.clustering.kmeans import KMeansModel, SILHOUETTE_MAX_SAMPLES
1212
from Orange.data import Table, Domain, DiscreteVariable, ContinuousVariable
13-
from Orange.data.util import get_unique_names
13+
from Orange.data.util import get_unique_names, array_equal
1414
from Orange.preprocess.impute import ReplaceUnknowns
1515
from Orange.widgets import widget, gui
1616
from Orange.widgets.settings import Setting
@@ -526,7 +526,7 @@ def set_data(self, data):
526526
self.data, old_data = data, self.data
527527

528528
# Do not needlessly recluster the data if X hasn't changed
529-
if old_data and self.data and np.array_equal(self.data.X, old_data.X):
529+
if old_data and self.data and array_equal(self.data.X, old_data.X):
530530
if self.auto_commit:
531531
self.send_data()
532532
else:

Orange/widgets/unsupervised/owlouvainclustering.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@
1616

1717
from Orange.clustering.louvain import table_to_knn_graph, Louvain
1818
from Orange.data import Table, DiscreteVariable
19-
from Orange.data.util import get_unique_names
19+
from Orange.data.util import get_unique_names, array_equal
2020
from Orange import preprocess
2121
from Orange.projection import PCA
22-
from Orange.statistics import util as ut
2322
from Orange.widgets import widget, gui, report
2423
from Orange.widgets.settings import DomainContextHandler, ContextSetting, \
2524
Setting
@@ -408,7 +407,7 @@ def set_data(self, data):
408407
# Make sure to properly enable/disable slider based on `apply_pca` setting
409408
self.controls.pca_components.setEnabled(self.apply_pca)
410409

411-
if prev_data and self.data and ut.array_equal(prev_data.X, self.data.X):
410+
if prev_data and self.data and array_equal(prev_data.X, self.data.X):
412411
if self.auto_commit:
413412
self._send_data()
414413
return

Orange/widgets/unsupervised/owmds.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import pyqtgraph as pg
1010

1111
from Orange.data import ContinuousVariable, Domain, Table, StringVariable
12+
from Orange.data.util import array_equal
1213
from Orange.distance import Euclidean
1314
from Orange.misc import DistMatrix
1415
from Orange.projection.manifold import torgerson, MDS
@@ -323,8 +324,7 @@ def _initialize(self):
323324
self.openContext(self.data)
324325
self._invalidated = not (matrix_existed and
325326
self.effective_matrix is not None and
326-
np.array_equal(effective_matrix,
327-
self.effective_matrix))
327+
array_equal(effective_matrix, self.effective_matrix))
328328
if self._invalidated:
329329
self.clear()
330330
self.graph.set_effective_matrix(self.effective_matrix)

0 commit comments

Comments
 (0)