Skip to content

Commit 94fc142

Browse files
committed
BinDefinition: Separate full and short labels
1 parent 04d9602 commit 94fc142

File tree

4 files changed

+34
-22
lines changed

4 files changed

+34
-22
lines changed

Orange/preprocess/discretize.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def _split_eq_width(self, min, max):
182182
class BinDefinition(NamedTuple):
183183
thresholds: np.ndarray # thresholds, including the top
184184
labels: List[str] # friendly-formatted thresholds
185+
short_labels: List[str] # shorter labels (e.g. simplified dates)
185186
width: Union[float, None] # widths, if uniform; otherwise None
186187
width_label: str # friendly-formatted width (e.g. '50' or '2 weeks')
187188

@@ -190,14 +191,25 @@ class BinDefinition(NamedTuple):
190191
# Name of the class has to be the same to match the namedtuple name
191192
# pylint: disable=function-redefined
192193
class BinDefinition(BinDefinition):
193-
def __new__(cls, thresholds, labels="%g", width=None, width_label=""):
194-
if isinstance(labels, str):
195-
labels = [labels % x for x in thresholds]
196-
elif isinstance(labels, Callable):
197-
labels = [labels(x) for x in thresholds]
194+
def __new__(cls, thresholds, labels="%g",
195+
short_labels=None, width=None, width_label=""):
196+
197+
def get_labels(fmt, default=None):
198+
if fmt is None:
199+
return default
200+
if isinstance(fmt, str):
201+
return [fmt % x for x in thresholds]
202+
elif isinstance(fmt, Callable):
203+
return [fmt(x) for x in thresholds]
204+
else:
205+
return fmt
206+
207+
labels = get_labels(labels)
208+
short_labels = get_labels(short_labels, labels)
198209
if not width_label and width is not None:
199210
width_label = f"{width:g}"
200-
return super().__new__(cls, thresholds, labels, width, width_label)
211+
return super().__new__(
212+
cls, thresholds, labels, short_labels, width, width_label)
201213

202214
@property
203215
def start(self) -> float:
@@ -299,7 +311,7 @@ def decimal_binnings(
299311
if min_bins <= nbins <= max_bins \
300312
and (not bins or bins[-1].nbins != nbins):
301313
bin_def = BinDefinition(mn_ + width * np.arange(nbins + 1),
302-
label_fmt, width)
314+
label_fmt, None, width)
303315
bins.append(bin_def)
304316
return bins
305317

@@ -362,12 +374,14 @@ def _time_binnings(mn, mx, min_pts, max_pts):
362374
continue
363375
times = [time.struct_time(t + (0, 0, 0)) for t in times]
364376
thresholds = [calendar.timegm(t) for t in times]
365-
labels = _simplified_labels([time.strftime(fmt, t) for t in times])
377+
labels = [time.strftime(fmt, t) for t in times]
378+
short_labels = _simplified_labels(labels)
366379
if place == 2 and step >= 7:
367380
unit_label = f"{step // 7} week{'s' * (step > 7)}"
368381
else:
369382
unit_label = f"{step} {unit}{'s' * (step > 1)}"
370-
new_bins = BinDefinition(thresholds, labels, None, unit_label)
383+
new_bins = BinDefinition(
384+
thresholds, labels, short_labels, None, unit_label)
371385
if not bins or new_bins.nbins != bins[-1].nbins:
372386
bins.append(new_bins)
373387
return bins
@@ -417,6 +431,7 @@ def _month_days(year, month,
417431

418432

419433
def _simplified_labels(labels):
434+
labels = labels[:]
420435
to_remove = "42"
421436
while True:
422437
firsts = {f for f, *_ in (lab.split() for lab in labels)}
@@ -442,8 +457,9 @@ def _unique_time_bins(unique):
442457
fmt = f'{"%y " if times[0][0] >= 1950 else "%Y "} %b %d'
443458
fmt += " %H:%M" * (len({t[2:] for t in times}) > 1)
444459
fmt += ":%S" * bool(np.all(unique % 60 == 0))
445-
return BinDefinition(_unique_thresholds(unique),
446-
[time.strftime(fmt, x) for x in times])
460+
labels = [time.strftime(fmt, x) for x in times]
461+
short_labels = _simplified_labels(labels)
462+
return BinDefinition(_unique_thresholds(unique), labels, short_labels)
447463

448464

449465
def _unique_thresholds(unique):

Orange/preprocess/tests/test_discretize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def setUp(self):
2626
def test_binning(self):
2727
def testbin(start, end):
2828
bins = _time_binnings(create(*start), create(*end), 3, 51)
29-
return [(bin.width_label, bin.labels, bin.thresholds)
29+
return [(bin.width_label, bin.short_labels, bin.thresholds)
3030
for bin in reversed(bins)]
3131

3232
self.assertEqual(

Orange/widgets/unsupervised/owsom.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -839,11 +839,7 @@ def set_color_bins(self):
839839
else:
840840
binning = decimal_binnings(col, min_bins=4)[-1]
841841
self.thresholds = binning.thresholds[1:-1]
842-
self.bin_labels = binning.labels[1:-1]
843-
# Second label may had been truncated; put back the missing part
844-
split0 = binning.labels[0].split()
845-
split1 = binning.labels[1].split()
846-
self.bin_labels[0] = " ".join(split0[:-len(split1)] + split1)
842+
self.bin_labels = (binning.labels[1:-1], binning.short_labels[1:-1])
847843
palette = ContinuousPaletteGenerator(*self.attr_color.colors)
848844
nbins = len(self.thresholds) + 1
849845
self.colors = [palette[i / (nbins - 1)] for i in range(nbins)]
@@ -881,11 +877,11 @@ def create_legend(self):
881877
self.set_legend_pos()
882878

883879
def _bin_names(self):
880+
labels, short_labels = self.bin_labels
884881
return \
885-
[f"< {self.bin_labels[0]}"] \
886-
+ [f"{x} - {y}"
887-
for x, y in zip(self.bin_labels, self.bin_labels[1:])] \
888-
+ [f"≥ {self.bin_labels[-1]}"]
882+
[f"< {labels[0]}"] \
883+
+ [f"{x} - {y}" for x, y in zip(labels, short_labels[1:])] \
884+
+ [f"≥ {labels[-1]}"]
889885

890886
def set_legend_pos(self):
891887
if self.legend is None:

Orange/widgets/visualize/owdistributions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ def _set_cont_ticks(self):
669669
axis = self.ploti.getAxis("bottom")
670670
if self.var and self.var.is_time:
671671
binning = self.binnings[self.number_of_bins]
672-
labels = np.array(binning.labels)
672+
labels = np.array(binning.short_labels)
673673
thresholds = np.array(binning.thresholds)
674674
lengths = np.array([len(lab) for lab in labels])
675675
slengths = set(lengths)

0 commit comments

Comments
 (0)