Skip to content

Commit 31ac974

Browse files
committed
Add helpers.get_aesthetic_limits
closes #906
1 parent c445aa2 commit 31ac974

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

doc/_quartodoc.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,13 @@ quartodoc:
562562
- figure_size
563563
- figure_format
564564

565+
- title: Tools
566+
desc: |
567+
Functions that you may occasioanally find helpful
568+
package: plotnine.helpers
569+
contents:
570+
- get_aesthetic_limits
571+
565572
- title: Datasets
566573
desc: |
567574
These datasets ship with the plotnine and you can import them with

doc/changelog.qmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ title: Changelog
7676

7777
- Gained the Anscombe Quartet dataset, [](:attr:`~plotnine.data.anscombe_quartet`).
7878

79+
- Gained new module `plotnine.helpers` to be a place for some helper functions.
80+
81+
- Gained new helper function [](:func:`~plotnine.helpers.get_aesthetic_limits`).
82+
7983
### Enhancements
8084

8185
- Included datasets [](:attr:`~plotnine.data.mpg`), [](:attr:`~plotnine.data.msleep`) and

plotnine/helpers.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from __future__ import annotations
2+
3+
from copy import deepcopy
4+
from typing import TYPE_CHECKING
5+
6+
if TYPE_CHECKING:
7+
from typing import Sequence
8+
9+
from plotnine import ggplot
10+
11+
__all__ = ("get_aesthetic_limits",)
12+
13+
14+
def get_aesthetic_limits(
15+
plot: ggplot,
16+
ae: str,
17+
) -> (
18+
tuple[float, float]
19+
| Sequence[str]
20+
| list[tuple[float]]
21+
| list[Sequence[str]]
22+
):
23+
"""
24+
Get the limits of an aesthetic
25+
26+
These are the limits before they are expanded.
27+
28+
Parameters
29+
----------
30+
plot :
31+
ggplot object
32+
33+
ae :
34+
Name of aesthetic
35+
36+
Returns
37+
-------
38+
out :
39+
The limits of the aesthetic. If the plot is facetted, (has many
40+
panels), it is a sequence of limits, one for each panel.
41+
"""
42+
plot = deepcopy(plot)
43+
plot._build()
44+
limits = [
45+
getattr(panel, ae).limits
46+
for panel in plot._build_objs.layout.panel_params
47+
]
48+
49+
return limits[0] if len(limits) == 1 else limits

tests/test_helpers.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from typing import cast
2+
3+
import numpy.testing as npt
4+
import pandas as pd
5+
6+
from plotnine import aes, facet_wrap, geom_bar, geom_point, ggplot
7+
from plotnine.helpers import get_aesthetic_limits
8+
9+
10+
class TestGetAestheticLimits:
11+
data = pd.DataFrame(
12+
{
13+
"x": [0, 1, 2, 3, 4, 5, 6],
14+
"y": [0, 1, 2, 3, 4, 5, 6],
15+
"g": list("aabbbcc"),
16+
}
17+
)
18+
19+
def test_continuous_limits(self):
20+
p = ggplot(self.data, aes("x", "y")) + geom_point()
21+
limits = cast("tuple[float, float]", get_aesthetic_limits(p, "x"))
22+
npt.assert_array_almost_equal(limits, [0, 6])
23+
24+
def test_discrete_limits(self):
25+
p = ggplot(self.data, aes("g")) + geom_bar()
26+
limits = cast("list[str]", get_aesthetic_limits(p, "x"))
27+
assert limits == ["a", "b", "c"]
28+
29+
def test_facet_limits(self):
30+
p = (
31+
ggplot(self.data, aes("x", "y"))
32+
+ geom_point()
33+
+ facet_wrap("g", scales="free_x")
34+
)
35+
limits = cast(
36+
"list[tuple[float, float]]", get_aesthetic_limits(p, "x")
37+
)
38+
npt.assert_array_almost_equal(limits[0], [0, 1])
39+
npt.assert_array_almost_equal(limits[1], [2, 4])
40+
npt.assert_array_almost_equal(limits[2], [5, 6])

0 commit comments

Comments
 (0)