Skip to content

Commit 5b82b64

Browse files
committed
Create broadcast_ae_value
1 parent b65c501 commit 5b82b64

2 files changed

Lines changed: 53 additions & 1 deletion

File tree

plotnine/mapping/_atomic.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ class ae_value(Generic[T]):
4242
aesthetic values. e.g. if a value is a tuple, we don't want it to be
4343
seen as a sequence of values when assigning it to a dataframe column.
4444
The subclasses should be able to recognise valid aesthetic values and
45-
repeat (using multiplication) the value any number of times.
45+
repeat (using multiplication) the value any number of times. i.e.
46+
broadcast the aesthetic.
4647
"""
4748

4849
value: T
@@ -176,3 +177,45 @@ def is_numeric(obj) -> bool:
176177
return all(is_numeric(a) and is_numeric(b) for a, b in obj)
177178
except (ValueError, TypeError):
178179
return False
180+
181+
182+
def broadcast_ae_value(value: T, ae: str, n: int) -> Sequence[T]:
183+
"""
184+
Repeat an aesthetic value n times
185+
186+
Parameters
187+
----------
188+
value :
189+
A single aesthetic value (e.g. a color tuple or linetype tuple)
190+
that should not be expanded element-wise.
191+
ae :
192+
Name of the aesthetic. Determines which [](`ae_value`) subclass
193+
validates and repeats the value.
194+
n :
195+
Number of times to repeat the value.
196+
197+
Returns
198+
-------
199+
:
200+
A sequence of length `n` containing the (validated) value.
201+
202+
Raises
203+
------
204+
ValueError
205+
If `ae` is not one of the aesthetics
206+
(`color`, `colour`, `fill`, `linetype`, `shape`)
207+
that has an "atomic" handler.
208+
"""
209+
lookup: dict[str, type[ae_value]] = {
210+
"color": color,
211+
"linetype": linetype,
212+
"colour": color,
213+
"fill": fill,
214+
"shape": shape,
215+
}
216+
try:
217+
return lookup[ae](value) * n
218+
except KeyError as err:
219+
raise ValueError(
220+
f"Aesthetic {ae!r} does not have a broadcast handler."
221+
) from err

tests/test_aes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
stat_ecdf,
1818
stat_function,
1919
)
20+
from plotnine.mapping._atomic import broadcast_ae_value, color
2021
from plotnine.mapping.aes import make_labels
2122

2223
data = pd.DataFrame(
@@ -134,3 +135,11 @@ def test_make_labels():
134135
mapping = {"y": "y", "color": ["Treatment", "Control"]}
135136
labels = make_labels(mapping)
136137
assert labels.color is None
138+
139+
140+
def test_broadcast_ae_value():
141+
result = broadcast_ae_value("red", "color", 3)
142+
assert result == [color("red").value] * 3
143+
144+
with pytest.raises(ValueError):
145+
broadcast_ae_value("red", "not_an_aesthetic", 3)

0 commit comments

Comments
 (0)