Skip to content

Commit 2577382

Browse files
committed
Add compose.Wrap
1 parent 787a0ad commit 2577382

File tree

10 files changed

+514
-8
lines changed

10 files changed

+514
-8
lines changed

doc/_quartodoc.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ quartodoc:
540540
include_attributes: false
541541
- Stack
542542
- Beside
543+
- Wrap
543544
- plot_spacer
544545
- plot_layout
545546

plotnine/_mpl/gridspec.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ class p9GridSpec(GridSpecBase):
2727
Gridspec for plotnine plots
2828
2929
This gridspec does not read any subplot parameter values from matplotlib's
30-
rcparams and the default a grid that fills up all the available space;
31-
there is no space along the edges and between the subplots.
30+
rcparams. And there is no space along the edges and between the subplots.
3231
3332
This gridspec can also be initialised while contained/nested in a given
3433
subplot.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from collections.abc import Iterator
2+
from dataclasses import InitVar, dataclass
3+
from typing import (
4+
Generic,
5+
Literal,
6+
Sequence,
7+
TypeVar,
8+
overload,
9+
)
10+
11+
import numpy as np
12+
13+
T = TypeVar("T")
14+
15+
16+
@dataclass
17+
class Grid(Generic[T]):
18+
nrow: InitVar[int]
19+
ncol: InitVar[int]
20+
items: InitVar[Sequence[T]]
21+
order: InitVar[Literal["row_major", "col_major"]] = "row_major"
22+
"""
23+
Put items into the grid left->right, top->bottom starting at `start`.
24+
Unfilled cells remain None. Returns the number of items written.
25+
"""
26+
27+
def __post_init__(
28+
self,
29+
nrow: int,
30+
ncol: int,
31+
items: Sequence[T],
32+
order: Literal["row_major", "col_major"],
33+
):
34+
self._grid = np.empty((nrow, ncol), dtype=object)
35+
36+
r, c = 0, 0
37+
if order == "row_major":
38+
for item in items:
39+
self[r, c] = item
40+
c += 1
41+
if c >= ncol:
42+
c, r = 0, r + 1
43+
else:
44+
for item in items:
45+
self[r, c] = item
46+
r += 1
47+
if r >= nrow:
48+
c, r = r + 1, 0
49+
50+
@overload
51+
def __getitem__(self, index: tuple[int, int]) -> T | None: ...
52+
53+
@overload
54+
def __getitem__(self, index: tuple[int, slice]) -> list[T | None]: ...
55+
56+
@overload
57+
def __getitem__(self, index: tuple[slice, int]) -> list[T | None]: ...
58+
59+
@overload
60+
def __getitem__(
61+
self,
62+
index: tuple[slice, slice],
63+
) -> list[list[T | None]]: ...
64+
65+
def __getitem__(
66+
self, index: tuple[int | slice, int | slice]
67+
) -> T | None | list[T | None] | list[list[T | None]]:
68+
"""
69+
Access grid items with 2D indexing:
70+
"""
71+
return self._grid[index] # pyright: ignore[reportReturnType]
72+
73+
def __setitem__(
74+
self,
75+
index: tuple[int | slice, slice | int],
76+
value: T | None | list[T | None] | list[list[T | None]],
77+
) -> None:
78+
self._grid[index] = value
79+
80+
def iter_rows(self) -> Iterator[list[T | None]]:
81+
"""
82+
Yield rows
83+
"""
84+
n = self._grid.shape[0]
85+
for row in range(n):
86+
yield self[row, :]
87+
88+
def iter_cols(self) -> Iterator[list[T | None]]:
89+
"""
90+
Yield cols
91+
"""
92+
n = self._grid.shape[1]
93+
for col in range(n):
94+
yield self[:, col]

0 commit comments

Comments
 (0)