Skip to content

Commit 123ad30

Browse files
committed
Goodbye Table.get_column(..., view=True), hello Table.set_column
1 parent e839a54 commit 123ad30

File tree

8 files changed

+37
-71
lines changed

8 files changed

+37
-71
lines changed

Orange/data/table.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ def add_column(self, variable, data, to_metas=None):
14361436
domain = Domain(attrs, classes, metavars)
14371437
new_table = self.transform(domain)
14381438
with new_table.unlocked(new_table.metas if to_metas else new_table.X):
1439-
new_table.get_column(variable, view=True)[:] = data
1439+
new_table.set_column(variable, data)
14401440
return new_table
14411441

14421442
@deprecated("array.base is not None for each subarray of Orange.data.Table (i.e. X, Y, W, metas)")
@@ -1585,7 +1585,7 @@ def shuffle(self):
15851585
self.W = self.W[ind]
15861586
self.ids = self.ids[ind]
15871587

1588-
@deprecated("Table.get_column(..., view=True)")
1588+
@deprecated("Table.get_column (or Table.set_column if you must)")
15891589
def get_column_view(self, index: Union[Integral, Variable]) -> np.ndarray:
15901590
"""
15911591
An obsolete function that was supposed to return a view with a column
@@ -1633,7 +1633,7 @@ def _get_column_view(self, index: Integral) -> np.ndarray:
16331633
else:
16341634
return self.metas[:, -1 - index]
16351635

1636-
def get_column(self, index, copy=False, view=False):
1636+
def get_column(self, index, copy=False):
16371637
"""
16381638
Return a column with values of `index`.
16391639
@@ -1644,54 +1644,55 @@ def get_column(self, index, copy=False, view=False):
16441644
Args:
16451645
index (int or str or Variable): attribute
16461646
copy (bool): if set to True, ensure the result is a copy, not a view
1647-
view (bool): if set to True, check that result is a view, not a copy
16481647
16491648
Returns:
16501649
column (np.array): data column
16511650
"""
1652-
if copy and view:
1653-
raise ValueError(
1654-
"incompatible arguments; `copy` and `view` cannot both be True")
1655-
16561651
if isinstance(index, Variable) and index not in self.domain:
16571652
if index.compute_value is None:
1658-
raise ValueError(
1659-
f"variable {index.name} is not in domain")
1660-
if view:
1661-
raise ValueError(
1662-
f"cannot create a view to derived variable {index.name}")
1653+
raise ValueError(f"variable {index.name} is not in domain")
16631654
return compute_column(index.compute_value, self)
16641655

16651656
mapper = None
1666-
is_primitive = isinstance(index, Variable) and index.is_primitive()
16671657
if not isinstance(index, Integral):
16681658
if isinstance(index, DiscreteVariable) \
16691659
and index.values != self.domain[index].values:
1670-
if view:
1671-
raise ValueError(
1672-
"cannot create a view to discrete variable "
1673-
f"{index.name} with different encoding")
1674-
else:
1675-
mapper = index.get_mapper_from(self.domain[index])
1660+
mapper = index.get_mapper_from(self.domain[index])
16761661
index = self.domain.index(index)
16771662

16781663
col = self._get_column_view(index)
16791664
if sp.issparse(col):
1680-
if view:
1681-
raise ValueError("cannot create a view into sparse matrix")
16821665
col = col.toarray().reshape(-1)
1666+
if col.dtype == object and self.domain[index].is_primitive():
1667+
col = col.astype(np.float64)
16831668
if mapper is not None:
16841669
col = mapper(col)
16851670
if copy and col.base is not None:
16861671
col = col.copy()
1687-
if is_primitive and col.dtype == object:
1688-
# TODO: This should fail if view=True. However, if a call wants a
1689-
# view, it may not need the cast (e.g. assigns values into column
1690-
# of metas).
1691-
# Either drop view argument OR don't cast if view.
1692-
col = col.astype(np.float64)
16931672
return col
16941673

1674+
def set_column(self, index: Union[int, str, Variable], data):
1675+
"""
1676+
Set the values in the given column do `data`.
1677+
1678+
This function may be useful, but try avoiding it.
1679+
1680+
Table (or the corresponding
1681+
part must be unlocked). If variable is discrete, its encoding must
1682+
match the variable in the domain.
1683+
1684+
Args:
1685+
index (int, str, Variable): index of a column
1686+
data (object): a single value or 1d array of length len(self)
1687+
"""
1688+
if not isinstance(index, Integral):
1689+
if isinstance(index, DiscreteVariable) \
1690+
and self.domain[index].values != index.values:
1691+
raise ValueError(f"cannot set data for variable {index.name} "
1692+
"with different encoding")
1693+
index = self.domain.index(index)
1694+
self._get_column_view(index)[:] = data
1695+
16951696
def _filter_is_defined(self, columns=None, negate=False):
16961697
# structure of function is obvious; pylint: disable=too-many-branches
16971698
def _sp_anynan(a):

Orange/data/tests/test_table.py

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -546,10 +546,6 @@ def test_get_column_proper_view(self):
546546
np.testing.assert_equal(col, data.X[:, 0])
547547
self.assertIs(col.base, data.X)
548548

549-
col = data.get_column(y, view=True)
550-
np.testing.assert_equal(col, data.X[:, 0])
551-
self.assertIs(col.base, data.X)
552-
553549
col = data.get_column(y, copy=True)
554550
np.testing.assert_equal(col, data.X[:, 0])
555551
self.assertIsNone(col.base)
@@ -565,31 +561,20 @@ def test_get_column_computed(self):
565561
np.testing.assert_equal(col2, [2, 4, 6])
566562
self.assertIsNone(col2.base)
567563

568-
self.assertRaises(ValueError, data.get_column, y2, view=True)
569-
570-
def test_get_column_wrong_arguments(self):
571-
self.assertRaises(
572-
ValueError, self.data.get_column, self.data.domain["y"],
573-
copy=True, view=True)
574-
575564
def test_get_column_discrete(self):
576565
data, d = self.data, self.data.domain["d"]
577566

578567
col = data.get_column(d)
579568
np.testing.assert_equal(col, [0, 0, 1])
580569
self.assertIs(col.base, data.X)
581570

582-
col = data.get_column(d, view=True)
583-
np.testing.assert_equal(col, [0, 0, 1])
584-
self.assertIs(col.base, data.X)
585-
586571
col = data.get_column(d, copy=True)
587572
np.testing.assert_equal(col, [0, 0, 1])
588573
self.assertIsNone(col.base)
589574

590575
e = DiscreteVariable("d", values=("a", "b"))
591576
assert e == d
592-
col = data.get_column(e, view=True)
577+
col = data.get_column(e)
593578
np.testing.assert_equal(col, [0, 0, 1])
594579
self.assertIs(col.base, data.X)
595580

@@ -603,10 +588,6 @@ def test_get_column_discrete(self):
603588
col = data.get_column(e)
604589
np.testing.assert_equal(col, [0, 0, 2])
605590

606-
e = DiscreteVariable("d", values=("a", "b", "c"))
607-
assert e == d # because that's how Variable mapping works
608-
self.assertRaises(ValueError, data.get_column, e, view=True)
609-
610591
with data.unlocked(data.X):
611592
data.X = sp.csr_matrix(data.X)
612593
e = DiscreteVariable("d", values=("a", "c", "b"))
@@ -625,19 +606,11 @@ def test_sparse(self):
625606
self.assertFalse(sp.issparse(col))
626607
np.testing.assert_equal(col, orig_y)
627608

628-
self.assertRaises(ValueError, data.get_column, y, view=True)
629-
630609
col = data.get_column(y, copy=True)
631610
self.assertFalse(sp.issparse(col))
632611
np.testing.assert_equal(col, orig_y)
633612

634613
def test_get_column_no_variable(self):
635-
self.assertRaises(ValueError, self.data.get_column,
636-
ContinuousVariable("y3"), view=True)
637-
638-
self.assertRaises(ValueError, self.data.get_column,
639-
ContinuousVariable("y3"), copy=True)
640-
641614
self.assertRaises(ValueError, self.data.get_column,
642615
ContinuousVariable("y3"))
643616

@@ -648,10 +621,6 @@ def test_index_by_int(self):
648621
np.testing.assert_equal(col, data.X[:, 0])
649622
self.assertIs(col.base, data.X)
650623

651-
col = data.get_column(0, view=True)
652-
np.testing.assert_equal(col, data.X[:, 0])
653-
self.assertIs(col.base, data.X)
654-
655624
col = data.get_column(0, copy=True)
656625
np.testing.assert_equal(col, data.X[:, 0])
657626
self.assertIsNone(col.base)
@@ -671,10 +640,6 @@ def test_index_by_int(self):
671640
np.testing.assert_equal(col, data.X[:, 0])
672641
self.assertIs(col.base, data.X)
673642

674-
col = data.get_column("y", view=True)
675-
np.testing.assert_equal(col, data.X[:, 0])
676-
self.assertIs(col.base, data.X)
677-
678643
col = data.get_column("y", copy=True)
679644
np.testing.assert_equal(col, data.X[:, 0])
680645
self.assertIsNone(col.base)

Orange/widgets/data/owneighbors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def _data_with_similarity(self, indices):
164164
distances = self.distances[indices]
165165
with neighbours.unlocked(neighbours.metas):
166166
if distances.size > 0:
167-
neighbours.get_column(dist_var, view=1)[:] = distances
167+
neighbours.set_column(dist_var, distances)
168168
return neighbours
169169

170170

Orange/widgets/data/tests/test_owrank.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ def test_scores_nan_sorting(self):
378378
"""Check NaNs are sorted last"""
379379
data = self.iris.copy()
380380
with data.unlocked():
381-
data.get_column('petal length', view=True)[:] = np.nan
381+
data.set_column('petal length', np.nan)
382382
self.send_signal(self.widget.Inputs.data, data)
383383
self.wait_until_finished()
384384

Orange/widgets/unsupervised/owhierarchicalclustering.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ def commit(self):
602602
domain = Orange.data.Domain(attrs, classes, metas + (clust_var,))
603603
data = items.transform(domain)
604604
with data.unlocked(data.metas):
605-
data.get_column(clust_var, view=True)[:] = c
605+
data.set_column(clust_var, c)
606606

607607
if selected_indices:
608608
selected_data = data[mask]

Orange/widgets/unsupervised/owkmeans.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,8 @@ def send_data(self):
545545
new_domain = add_columns(domain, metas=[cluster_var, silhouette_var])
546546
new_table = self.data.transform(new_domain)
547547
with new_table.unlocked(new_table.metas):
548-
new_table.get_column(cluster_var, view=True)[:] = clust_ids
549-
new_table.get_column(silhouette_var, view=True)[:] = scores
548+
new_table.set_column(cluster_var, clust_ids)
549+
new_table.set_column(silhouette_var, scores)
550550

551551
domain_attributes = set(domain.attributes)
552552
centroid_attributes = [

Orange/widgets/unsupervised/owlouvainclustering.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ def _send_data(self):
387387
new_domain = add_columns(domain, metas=[cluster_var])
388388
new_table = self.data.transform(new_domain)
389389
with new_table.unlocked(new_table.metas):
390-
new_table.get_column(cluster_var, view=True)[:] = new_partition
390+
new_table.set_column(cluster_var, new_partition)
391391

392392
self.Outputs.annotated_data.send(new_table)
393393

Orange/widgets/unsupervised/tests/test_owlouvain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_empty_dataset(self):
6565
meta_var = ContinuousVariable(name='meta_var')
6666
table = Table.from_domain(domain=Domain([], metas=[meta_var]), n_rows=5)
6767
with table.unlocked():
68-
table.get_column(meta_var, view=True)[:] = meta
68+
table.set_column(meta_var, meta)
6969

7070
self.send_signal(self.widget.Inputs.data, table)
7171
self.commit_and_wait()

0 commit comments

Comments
 (0)