Skip to content

Commit 7137d0d

Browse files
committed
Goodbye Table.get_column(..., view=True), hello Table.set_column
1 parent 582ce2e commit 7137d0d

File tree

8 files changed

+37
-72
lines changed

8 files changed

+37
-72
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
def is_sparse(self):
@@ -1565,7 +1565,7 @@ def shuffle(self):
15651565
self.W = self.W[ind]
15661566
self.ids = self.ids[ind]
15671567

1568-
@deprecated("Table.get_column(..., view=True)")
1568+
@deprecated("Table.get_column (or Table.set_column if you must)")
15691569
def get_column_view(self, index: Union[Integral, Variable]) -> np.ndarray:
15701570
"""
15711571
An obsolete function that was supposed to return a view with a column
@@ -1613,7 +1613,7 @@ def _get_column_view(self, index: Integral) -> np.ndarray:
16131613
else:
16141614
return self.metas[:, -1 - index]
16151615

1616-
def get_column(self, index, copy=False, view=False):
1616+
def get_column(self, index, copy=False):
16171617
"""
16181618
Return a column with values of `index`.
16191619
@@ -1624,54 +1624,55 @@ def get_column(self, index, copy=False, view=False):
16241624
Args:
16251625
index (int or str or Variable): attribute
16261626
copy (bool): if set to True, ensure the result is a copy, not a view
1627-
view (bool): if set to True, check that result is a view, not a copy
16281627
16291628
Returns:
16301629
column (np.array): data column
16311630
"""
1632-
if copy and view:
1633-
raise ValueError(
1634-
"incompatible arguments; `copy` and `view` cannot both be True")
1635-
16361631
if isinstance(index, Variable) and index not in self.domain:
16371632
if index.compute_value is None:
1638-
raise ValueError(
1639-
f"variable {index.name} is not in domain")
1640-
if view:
1641-
raise ValueError(
1642-
f"cannot create a view to derived variable {index.name}")
1633+
raise ValueError(f"variable {index.name} is not in domain")
16431634
return compute_column(index.compute_value, self)
16441635

16451636
mapper = None
1646-
is_primitive = isinstance(index, Variable) and index.is_primitive()
16471637
if not isinstance(index, Integral):
16481638
if isinstance(index, DiscreteVariable) \
16491639
and index.values != self.domain[index].values:
1650-
if view:
1651-
raise ValueError(
1652-
"cannot create a view to discrete variable "
1653-
f"{index.name} with different encoding")
1654-
else:
1655-
mapper = index.get_mapper_from(self.domain[index])
1640+
mapper = index.get_mapper_from(self.domain[index])
16561641
index = self.domain.index(index)
16571642

16581643
col = self._get_column_view(index)
16591644
if sp.issparse(col):
1660-
if view:
1661-
raise ValueError("cannot create a view into sparse matrix")
16621645
col = col.toarray().reshape(-1)
1646+
if col.dtype == object and self.domain[index].is_primitive():
1647+
col = col.astype(np.float64)
16631648
if mapper is not None:
16641649
col = mapper(col)
16651650
if copy and col.base is not None:
16661651
col = col.copy()
1667-
if is_primitive and col.dtype == object:
1668-
# TODO: This should fail if view=True. However, if a call wants a
1669-
# view, it may not need the cast (e.g. assigns values into column
1670-
# of metas).
1671-
# Either drop view argument OR don't cast if view.
1672-
col = col.astype(np.float64)
16731652
return col
16741653

1654+
def set_column(self, index: Union[int, str, Variable], data):
1655+
"""
1656+
Set the values in the given column do `data`.
1657+
1658+
This function may be useful, but try avoiding it.
1659+
1660+
Table (or the corresponding
1661+
part must be unlocked). If variable is discrete, its encoding must
1662+
match the variable in the domain.
1663+
1664+
Args:
1665+
index (int, str, Variable): index of a column
1666+
data (object): a single value or 1d array of length len(self)
1667+
"""
1668+
if not isinstance(index, Integral):
1669+
if isinstance(index, DiscreteVariable) \
1670+
and self.domain[index].values != index.values:
1671+
raise ValueError(f"cannot set data for variable {index.name} "
1672+
"with different encoding")
1673+
index = self.domain.index(index)
1674+
self._get_column_view(index)[:] = data
1675+
16751676
def _filter_is_defined(self, columns=None, negate=False):
16761677
# structure of function is obvious; pylint: disable=too-many-branches
16771678
def _sp_anynan(a):

Orange/data/tests/test_table.py

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import numpy as np
77
import scipy.sparse as sp
88

9-
import Orange
109
from Orange.data import (
1110
ContinuousVariable, DiscreteVariable, StringVariable,
1211
Domain, Table, IsDefined, FilterContinuous, Values, FilterString,
@@ -533,10 +532,6 @@ def test_get_column_proper_view(self):
533532
np.testing.assert_equal(col, data.X[:, 0])
534533
self.assertIs(col.base, data.X)
535534

536-
col = data.get_column(y, view=True)
537-
np.testing.assert_equal(col, data.X[:, 0])
538-
self.assertIs(col.base, data.X)
539-
540535
col = data.get_column(y, copy=True)
541536
np.testing.assert_equal(col, data.X[:, 0])
542537
self.assertIsNone(col.base)
@@ -552,31 +547,20 @@ def test_get_column_computed(self):
552547
np.testing.assert_equal(col2, [2, 4, 6])
553548
self.assertIsNone(col2.base)
554549

555-
self.assertRaises(ValueError, data.get_column, y2, view=True)
556-
557-
def test_get_column_wrong_arguments(self):
558-
self.assertRaises(
559-
ValueError, self.data.get_column, self.data.domain["y"],
560-
copy=True, view=True)
561-
562550
def test_get_column_discrete(self):
563551
data, d = self.data, self.data.domain["d"]
564552

565553
col = data.get_column(d)
566554
np.testing.assert_equal(col, [0, 0, 1])
567555
self.assertIs(col.base, data.X)
568556

569-
col = data.get_column(d, view=True)
570-
np.testing.assert_equal(col, [0, 0, 1])
571-
self.assertIs(col.base, data.X)
572-
573557
col = data.get_column(d, copy=True)
574558
np.testing.assert_equal(col, [0, 0, 1])
575559
self.assertIsNone(col.base)
576560

577561
e = DiscreteVariable("d", values=("a", "b"))
578562
assert e == d
579-
col = data.get_column(e, view=True)
563+
col = data.get_column(e)
580564
np.testing.assert_equal(col, [0, 0, 1])
581565
self.assertIs(col.base, data.X)
582566

@@ -590,10 +574,6 @@ def test_get_column_discrete(self):
590574
col = data.get_column(e)
591575
np.testing.assert_equal(col, [0, 0, 2])
592576

593-
e = DiscreteVariable("d", values=("a", "b", "c"))
594-
assert e == d # because that's how Variable mapping works
595-
self.assertRaises(ValueError, data.get_column, e, view=True)
596-
597577
with data.unlocked(data.X):
598578
data.X = sp.csr_matrix(data.X)
599579
e = DiscreteVariable("d", values=("a", "c", "b"))
@@ -612,19 +592,11 @@ def test_sparse(self):
612592
self.assertFalse(sp.issparse(col))
613593
np.testing.assert_equal(col, orig_y)
614594

615-
self.assertRaises(ValueError, data.get_column, y, view=True)
616-
617595
col = data.get_column(y, copy=True)
618596
self.assertFalse(sp.issparse(col))
619597
np.testing.assert_equal(col, orig_y)
620598

621599
def test_get_column_no_variable(self):
622-
self.assertRaises(ValueError, self.data.get_column,
623-
ContinuousVariable("y3"), view=True)
624-
625-
self.assertRaises(ValueError, self.data.get_column,
626-
ContinuousVariable("y3"), copy=True)
627-
628600
self.assertRaises(ValueError, self.data.get_column,
629601
ContinuousVariable("y3"))
630602

@@ -635,10 +607,6 @@ def test_index_by_int(self):
635607
np.testing.assert_equal(col, data.X[:, 0])
636608
self.assertIs(col.base, data.X)
637609

638-
col = data.get_column(0, view=True)
639-
np.testing.assert_equal(col, data.X[:, 0])
640-
self.assertIs(col.base, data.X)
641-
642610
col = data.get_column(0, copy=True)
643611
np.testing.assert_equal(col, data.X[:, 0])
644612
self.assertIsNone(col.base)
@@ -658,10 +626,6 @@ def test_index_by_int(self):
658626
np.testing.assert_equal(col, data.X[:, 0])
659627
self.assertIs(col.base, data.X)
660628

661-
col = data.get_column("y", view=True)
662-
np.testing.assert_equal(col, data.X[:, 0])
663-
self.assertIs(col.base, data.X)
664-
665629
col = data.get_column("y", copy=True)
666630
np.testing.assert_equal(col, data.X[:, 0])
667631
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
@@ -770,7 +770,7 @@ def commit(self):
770770
domain = Orange.data.Domain(attrs, classes, metas + (clust_var,))
771771
data = items.transform(domain)
772772
with data.unlocked(data.metas):
773-
data.get_column(clust_var, view=True)[:] = c
773+
data.set_column(clust_var, c)
774774

775775
if selected_indices:
776776
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)