plotnine 0.15.0a3__py3-none-any.whl → 0.15.0a5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,9 +12,10 @@ from collections.abc import Iterable, Sequence
12
12
  from contextlib import suppress
13
13
  from copy import deepcopy
14
14
  from dataclasses import field
15
- from typing import TYPE_CHECKING, cast, overload
15
+ from typing import TYPE_CHECKING
16
16
  from warnings import warn
17
17
 
18
+ import mizani._colors.utils as color_utils
18
19
  import numpy as np
19
20
  import pandas as pd
20
21
  from pandas.core.groupby import DataFrameGroupBy
@@ -26,12 +27,10 @@ if TYPE_CHECKING:
26
27
  from typing import Any, Callable, Literal, TypeVar
27
28
 
28
29
  import numpy.typing as npt
29
- from matplotlib.typing import ColorType
30
30
  from typing_extensions import TypeGuard
31
31
 
32
32
  from plotnine.typing import (
33
33
  AnyArrayLike,
34
- AnySeries,
35
34
  DataLike,
36
35
  FloatArray,
37
36
  FloatArrayLike,
@@ -60,6 +59,8 @@ BOX_LOCATIONS: dict[str, tuple[float, float]] = {
60
59
  "centre": (0.5, 0.5),
61
60
  }
62
61
 
62
+ to_rgba = color_utils.to_rgba
63
+
63
64
 
64
65
  def is_scalar(val):
65
66
  """
@@ -361,7 +362,7 @@ def _id_var(x: AnyArrayLike, drop: bool = False) -> list[int]:
361
362
  lst = match(x, levels)
362
363
  lst = [item + 1 for item in lst]
363
364
 
364
- return lst # pyright: ignore[reportReturnType]
365
+ return lst
365
366
 
366
367
 
367
368
  def join_keys(x, y, by=None):
@@ -530,105 +531,6 @@ def remove_missing(
530
531
  return data
531
532
 
532
533
 
533
- @overload
534
- def to_rgba(colors: ColorType, alpha: float) -> ColorType: ...
535
-
536
-
537
- @overload
538
- def to_rgba(
539
- colors: Sequence[ColorType], alpha: float
540
- ) -> Sequence[ColorType] | ColorType: ...
541
-
542
-
543
- @overload
544
- def to_rgba(
545
- colors: AnySeries, alpha: AnySeries
546
- ) -> Sequence[ColorType] | ColorType: ...
547
-
548
-
549
- def to_rgba(
550
- colors: Sequence[ColorType] | AnySeries | ColorType,
551
- alpha: float | Sequence[float] | AnySeries,
552
- ) -> Sequence[ColorType] | ColorType:
553
- """
554
- Convert hex colors to rgba values.
555
-
556
- Parameters
557
- ----------
558
- colors : iterable | str
559
- colors to convert
560
- alphas : iterable | float
561
- alpha values
562
-
563
- Returns
564
- -------
565
- out : ndarray | tuple
566
- rgba color(s)
567
-
568
- Notes
569
- -----
570
- Matplotlib plotting functions only accept scalar
571
- alpha values. Hence no two objects with different
572
- alpha values may be plotted in one call. This would
573
- make plots with continuous alpha values innefficient.
574
- However :), the colors can be rgba hex values or
575
- list-likes and the alpha dimension will be respected.
576
- """
577
-
578
- def is_iterable(var):
579
- return np.iterable(var) and not isinstance(var, str)
580
-
581
- def has_alpha(c):
582
- return (isinstance(c, tuple) and len(c) == 4) or (
583
- isinstance(c, str) and len(c) == 9 and c[0] == "#"
584
- )
585
-
586
- def no_color(c):
587
- return c is None or c.lower() in ("none", "")
588
-
589
- def to_rgba_hex(c: ColorType, a: float) -> str:
590
- """
591
- Convert rgb color to rgba hex value
592
-
593
- If color c has an alpha channel, then alpha value
594
- a is ignored
595
- """
596
- from matplotlib.colors import colorConverter, to_hex
597
-
598
- if c in ("None", "none"):
599
- return c
600
-
601
- _has_alpha = has_alpha(c)
602
- c = to_hex(c, keep_alpha=_has_alpha)
603
-
604
- if not _has_alpha:
605
- arr = colorConverter.to_rgba(c, a)
606
- return to_hex(arr, keep_alpha=True)
607
-
608
- return c
609
-
610
- if is_iterable(colors):
611
- colors = cast("Sequence[ColorType]", colors)
612
-
613
- if all(no_color(c) for c in colors):
614
- return "none"
615
-
616
- if isinstance(alpha, (Sequence, pd.Series)):
617
- return [to_rgba_hex(c, a) for c, a in zip(colors, alpha)]
618
- else:
619
- return [to_rgba_hex(c, alpha) for c in colors]
620
- else:
621
- colors = cast("ColorType", colors)
622
-
623
- if no_color(colors):
624
- return colors
625
-
626
- if isinstance(alpha, (Sequence, pd.Series)):
627
- return [to_rgba_hex(colors, a) for a in alpha]
628
- else:
629
- return to_rgba_hex(colors, alpha)
630
-
631
-
632
534
  def groupby_apply(
633
535
  df: pd.DataFrame,
634
536
  cols: str | list[str],
plotnine/doctools.py CHANGED
@@ -71,7 +71,7 @@ STAT_SIGNATURE_TPL = """
71
71
 
72
72
  common_params_doc = {
73
73
  "mapping": """\
74
- Aesthetic mappings created with [aes](:class:`plotnine.mapping.aes`). If \
74
+ Aesthetic mappings created with [aes](:class:`plotnine.mapping.aes.aes`). If \
75
75
  specified and `inherit_aes=True`{.py}, it is combined with the default \
76
76
  mapping for the plot. You must supply mapping if there is no plot mapping.""",
77
77
  "data": """\
@@ -103,7 +103,7 @@ the final image is in vector format.""",
103
103
 
104
104
 
105
105
  GEOM_PARAMS_TPL = """
106
- mapping : ~plotnine.mapping.aes, default=None
106
+ mapping : ~plotnine.mapping.aes.aes, default=None
107
107
  {mapping}
108
108
  {_aesthetics_doc}
109
109
  data : ~pandas.DataFrame, default=None
@@ -124,7 +124,7 @@ raster : bool, default={default_raster}
124
124
  """
125
125
 
126
126
  STAT_PARAMS_TPL = """
127
- mapping : ~plotnine.mapping.aes, default=None
127
+ mapping : ~plotnine.mapping.aes.aes, default=None
128
128
  {mapping}
129
129
  {_aesthetics_doc}
130
130
  data : ~pandas.DataFrame, default=None
@@ -64,16 +64,16 @@ class annotate:
64
64
  def __init__(
65
65
  self,
66
66
  geom: str | type[geom_base_class],
67
- x: float | None = None,
68
- y: float | None = None,
69
- xmin: float | None = None,
70
- xmax: float | None = None,
71
- xend: float | None = None,
72
- xintercept: float | None = None,
73
- ymin: float | None = None,
74
- ymax: float | None = None,
75
- yend: float | None = None,
76
- yintercept: float | None = None,
67
+ x: float | list[float] | None = None,
68
+ y: float | list[float] | None = None,
69
+ xmin: float | list[float] | None = None,
70
+ xmax: float | list[float] | None = None,
71
+ xend: float | list[float] | None = None,
72
+ xintercept: float | list[float] | None = None,
73
+ ymin: float | list[float] | None = None,
74
+ ymax: float | list[float] | None = None,
75
+ yend: float | list[float] | None = None,
76
+ yintercept: float | list[float] | None = None,
77
77
  **kwargs: Any,
78
78
  ):
79
79
  variables = locals()
plotnine/geoms/geom.py CHANGED
@@ -2,18 +2,20 @@ from __future__ import annotations
2
2
 
3
3
  import typing
4
4
  from abc import ABC
5
+ from contextlib import suppress
5
6
  from copy import deepcopy
6
7
  from itertools import chain, repeat
7
8
 
9
+ import numpy as np
10
+
8
11
  from .._utils import (
9
12
  data_mapping_as_kwargs,
10
- is_list_like,
11
13
  remove_missing,
12
14
  )
13
15
  from .._utils.registry import Register, Registry
14
16
  from ..exceptions import PlotnineError
15
17
  from ..layer import layer
16
- from ..mapping.aes import is_valid_aesthetic, rename_aesthetics
18
+ from ..mapping.aes import rename_aesthetics
17
19
  from ..mapping.evaluation import evaluate
18
20
  from ..positions.position import position
19
21
  from ..stats.stat import stat
@@ -179,11 +181,16 @@ class geom(ABC, metaclass=Register):
179
181
  ----------
180
182
  data :
181
183
  Data
184
+ """
182
185
 
183
- Returns
184
- -------
185
- out :
186
- Parameters used by the geoms.
186
+ def setup_aes_params(self, data: pd.DataFrame):
187
+ """
188
+ Override this method to verify and/or adjust aesthetic parameters
189
+
190
+ Parameters
191
+ ----------
192
+ data :
193
+ Data
187
194
  """
188
195
 
189
196
  def setup_data(self, data: pd.DataFrame) -> pd.DataFrame:
@@ -239,6 +246,9 @@ class geom(ABC, metaclass=Register):
239
246
  :
240
247
  Data used for drawing the geom.
241
248
  """
249
+ from plotnine.mapping import _atomic as atomic
250
+ from plotnine.mapping._atomic import ae_value
251
+
242
252
  missing_aes = (
243
253
  self.DEFAULT_AES.keys()
244
254
  - self.aes_params.keys()
@@ -255,23 +265,34 @@ class geom(ABC, metaclass=Register):
255
265
  data[ae] = evaled[ae]
256
266
 
257
267
  num_panels = len(data["PANEL"].unique()) if "PANEL" in data else 1
268
+ across_panels = num_panels > 1 and not self.params["inherit_aes"]
258
269
 
259
- # Aesthetics set as parameters to the geom/stat
270
+ # Aesthetics set as parameters in the geom/stat
260
271
  for ae, value in self.aes_params.items():
261
- try:
272
+ if isinstance(value, (str, int, float, np.integer, np.floating)):
273
+ data[ae] = value
274
+ elif isinstance(value, ae_value):
275
+ data[ae] = value * len(data)
276
+ elif across_panels:
277
+ value = list(chain(*repeat(value, num_panels)))
262
278
  data[ae] = value
263
- except ValueError as e:
264
- # sniff out the special cases, like custom
265
- # tupled linetypes, shapes and colors
266
- if is_valid_aesthetic(value, ae):
267
- data[ae] = [value] * len(data)
268
- elif num_panels > 1 and is_list_like(value):
269
- data[ae] = list(chain(*repeat(value, num_panels)))
270
- else:
271
- msg = (
272
- f"'{value}' does not look like a "
273
- f"valid value for `{ae}`"
274
- )
279
+ else:
280
+ # Try to make sense of aesthetics whose values can be tuples
281
+ # or sequences of sorts.
282
+ ae_value_cls: type[ae_value] | None = getattr(atomic, ae, None)
283
+ if ae_value_cls:
284
+ with suppress(ValueError):
285
+ data[ae] = ae_value_cls(value) * len(data)
286
+ continue
287
+
288
+ # This should catch the aesthetic assignments to
289
+ # non-numeric or non-string values or sequence of values.
290
+ # e.g. x=datetime, x=Sequence[datetime],
291
+ # x=Sequence[float], shape=Sequence[str]
292
+ try:
293
+ data[ae] = value
294
+ except ValueError as e:
295
+ msg = f"'{ae}={value}' does not look like a valid value"
275
296
  raise PlotnineError(msg) from e
276
297
 
277
298
  return data
plotnine/layer.py CHANGED
@@ -257,6 +257,7 @@ class layer:
257
257
  """
258
258
  self.geom.params["zorder"] = self.zorder
259
259
  self.geom.params["raster"] = self.raster
260
+ self.geom.params["inherit_aes"] = self.inherit_aes
260
261
 
261
262
  def compute_aesthetics(self, plot: ggplot):
262
263
  """
@@ -330,6 +331,7 @@ class layer:
330
331
 
331
332
  self.geom.params.update(self.stat.params)
332
333
  self.geom.setup_params(data)
334
+ self.geom.setup_aes_params(data)
333
335
  data = self.geom.setup_data(data)
334
336
 
335
337
  check_required_aesthetics(
@@ -0,0 +1,178 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import suppress
4
+ from dataclasses import dataclass
5
+ from typing import (
6
+ Any,
7
+ Generic,
8
+ Literal,
9
+ Sequence,
10
+ TypeAlias,
11
+ TypeVar,
12
+ )
13
+
14
+ import numpy as np
15
+ from mizani._colors.utils import is_color_tuple
16
+
17
+ # NOTE:For now we shall use these class privately and not list them
18
+ # in documentation. We can't deal with assigning Sequence[ae_value]
19
+ # to an aesthetic.
20
+
21
+ __all__ = (
22
+ "linetype",
23
+ "color",
24
+ "colour",
25
+ "fill",
26
+ "shape",
27
+ )
28
+
29
+ T = TypeVar("T")
30
+
31
+ ShapeType: TypeAlias = (
32
+ str | tuple[int, Literal[0, 1, 2], float] | Sequence[tuple[float, float]]
33
+ )
34
+
35
+
36
+ @dataclass
37
+ class ae_value(Generic[T]):
38
+ """
39
+ Atomic aesthetic value
40
+
41
+ The goal of this base class is simplify working with the more complex
42
+ aesthetic values. e.g. if a value is a tuple, we don't want it to be
43
+ seen as a sequence of values when assigning it to a dataframe column.
44
+ The subclasses should be able to recognise valid aesthetic values and
45
+ repeat (using multiplication) the value any number of times.
46
+ """
47
+
48
+ value: T
49
+
50
+ def __mul__(self, n: int) -> Sequence[T]:
51
+ """
52
+ Repeat value n times
53
+ """
54
+ return [self.value] * n
55
+
56
+
57
+ @dataclass
58
+ class linetype(ae_value[str | tuple]):
59
+ """
60
+ A single linetype value
61
+ """
62
+
63
+ def __post_init__(self):
64
+ value = self.value
65
+ named = {
66
+ " ",
67
+ "",
68
+ "-",
69
+ "--",
70
+ "-.",
71
+ ":",
72
+ "None",
73
+ "none",
74
+ "dashdot",
75
+ "dashed",
76
+ "dotted",
77
+ "solid",
78
+ }
79
+ if self.value in named:
80
+ return
81
+
82
+ # tuple of the form (offset, (on, off, on, off, ...))
83
+ # e.g (0, (1, 2))
84
+ if (
85
+ isinstance(value, tuple)
86
+ and isinstance(value[0], int)
87
+ and isinstance(value[1], tuple)
88
+ and len(value[1]) % 2 == 0
89
+ and all(isinstance(x, int) for x in value[1])
90
+ ):
91
+ return
92
+
93
+ raise ValueError(f"{value} is not a known linetype.")
94
+
95
+
96
+ @dataclass
97
+ class color(ae_value[str | tuple]):
98
+ """
99
+ A single color value
100
+ """
101
+
102
+ def __post_init__(self):
103
+ if isinstance(self.value, str):
104
+ return
105
+ elif is_color_tuple(self.value):
106
+ self.value = tuple(self.value)
107
+ return
108
+
109
+ raise ValueError(f"{self.value} is not a known color.")
110
+
111
+
112
+ colour = color
113
+
114
+
115
+ @dataclass
116
+ class fill(color):
117
+ """
118
+ A single color value
119
+ """
120
+
121
+
122
+ @dataclass
123
+ class shape(ae_value[ShapeType]):
124
+ """
125
+ A single shape value
126
+ """
127
+
128
+ def __post_init__(self):
129
+ from matplotlib.path import Path
130
+
131
+ from ..scales.scale_shape import FILLED_SHAPES, UNFILLED_SHAPES
132
+
133
+ value = self.value
134
+
135
+ with suppress(TypeError):
136
+ if value in (FILLED_SHAPES | UNFILLED_SHAPES):
137
+ return
138
+
139
+ if isinstance(value, Path):
140
+ return
141
+
142
+ # tuple of the form (numsides, style, angle)
143
+ # where style is in the range [0, 3]
144
+ # e.g (4, 1, 45)
145
+ if (
146
+ isinstance(value, tuple)
147
+ and len(value) == 3
148
+ and isinstance(value[0], int)
149
+ and value[1] in (0, 1, 2)
150
+ and isinstance(value[2], (float, int))
151
+ ):
152
+ return
153
+
154
+ if is_shape_points(value):
155
+ self.value = tuple(value) # pyright: ignore[reportAttributeAccessIssue]
156
+ return
157
+
158
+ raise ValueError(f"{value} is not a known shape.")
159
+
160
+
161
+ def is_shape_points(obj: Any) -> bool:
162
+ """
163
+ Return True if obj is like Sequence[tuple[float, float]]
164
+ """
165
+
166
+ def is_numeric(obj) -> bool:
167
+ """
168
+ Return True if obj is a python or numpy float or integer
169
+ """
170
+ return isinstance(obj, (float, int, np.floating, np.integer))
171
+
172
+ if not iter(obj):
173
+ return False
174
+
175
+ try:
176
+ return all(is_numeric(a) and is_numeric(b) for a, b in obj)
177
+ except (ValueError, TypeError):
178
+ return False
plotnine/mapping/aes.py CHANGED
@@ -8,7 +8,9 @@ from dataclasses import fields
8
8
  from functools import cached_property
9
9
  from typing import TYPE_CHECKING, Any, Dict
10
10
 
11
+ import numpy as np
11
12
  import pandas as pd
13
+ from mizani._colors.utils import is_color_tuple
12
14
 
13
15
  from ..iapi import labels_view
14
16
  from .evaluation import after_stat, stage
@@ -538,23 +540,23 @@ def make_labels(mapping: dict[str, Any] | aes) -> labels_view:
538
540
  )
539
541
 
540
542
 
541
- def is_valid_aesthetic(value: Any, ae: str) -> bool:
543
+ class RepeatAesthetic:
542
544
  """
543
- Return True if `value` looks valid.
545
+ Repeat an Aeshetic a given number of times
544
546
 
545
- Parameters
546
- ----------
547
- value :
548
- Value to check
549
- ae :
550
- Aesthetic name
547
+ The methods in this class know how to create sequences of aesthetics
548
+ whose values may not be scalar.
551
549
 
552
- Notes
553
- -----
554
- There are no guarantees that he value is spot on
555
- valid.
550
+ Some aesthetics may have valid values that are not scalar. e.g.
551
+ sequences. Inserting one of such a value in a dataframe as a column
552
+ would either lead to the wrong input or fail. The s
556
553
  """
557
- if ae == "linetype":
554
+
555
+ @staticmethod
556
+ def linetype(value: Any, n: int) -> Sequence[Any]:
557
+ """
558
+ Repeat linetypes
559
+ """
558
560
  named = {
559
561
  "solid",
560
562
  "dashed",
@@ -569,47 +571,75 @@ def is_valid_aesthetic(value: Any, ae: str) -> bool:
569
571
  "",
570
572
  }
571
573
  if value in named:
572
- return True
574
+ return [value] * n
573
575
 
574
576
  # tuple of the form (offset, (on, off, on, off, ...))
575
577
  # e.g (0, (1, 2))
576
- conditions = [
577
- isinstance(value, tuple),
578
- isinstance(value[0], int),
579
- isinstance(value[1], tuple),
580
- len(value[1]) % 2 == 0,
581
- all(isinstance(x, int) for x in value[1]),
582
- ]
583
- return all(conditions)
584
-
585
- elif ae == "shape":
578
+ if (
579
+ isinstance(value, tuple)
580
+ and isinstance(value[0], int)
581
+ and isinstance(value[1], tuple)
582
+ and len(value[1]) % 2 == 0
583
+ and all(isinstance(x, int) for x in value[1])
584
+ ):
585
+ return [value] * n
586
+
587
+ raise ValueError(f"{value} is not a known linetype.")
588
+
589
+ @staticmethod
590
+ def color(value: Any, n: int) -> Sequence[Any]:
591
+ """
592
+ Repeat colors
593
+ """
586
594
  if isinstance(value, str):
587
- return True
595
+ return [value] * n
596
+ if is_color_tuple(value):
597
+ return [tuple(value)] * n
598
+
599
+ raise ValueError(f"{value} is not a known color.")
600
+
601
+ fill = color
588
602
 
603
+ @staticmethod
604
+ def shape(value: Any, n: int) -> Any:
605
+ """
606
+ Repeat shapes
607
+ """
608
+ if isinstance(value, str):
609
+ return [value] * n
589
610
  # tuple of the form (numsides, style, angle)
590
611
  # where style is in the range [0, 3]
591
612
  # e.g (4, 1, 45)
592
- conditions = [
593
- isinstance(value, tuple),
594
- all(isinstance(x, int) for x in value),
595
- 0 <= value[1] < 3,
596
- ]
597
- return all(conditions)
598
-
599
- elif ae in {"color", "fill"}:
600
- if isinstance(value, str):
601
- return True
602
- with suppress(TypeError):
603
- if isinstance(value, (tuple, list)) and all(
604
- 0 <= x <= 1 for x in value
605
- ):
606
- return True
607
- return False
613
+ if (
614
+ isinstance(value, tuple)
615
+ and all(isinstance(x, int) for x in value)
616
+ and 0 <= value[1] < 3
617
+ ):
618
+ return [value] * n
619
+
620
+ if is_shape_points(value):
621
+ return [tuple(value)] * n
622
+
623
+ raise ValueError(f"{value} is not a know shape.")
608
624
 
609
- # For any other aesthetics we return False to allow
610
- # for special cases to be discovered and then coded
611
- # for appropriately.
612
- return False
625
+
626
+ def is_shape_points(obj: Any) -> bool:
627
+ """
628
+ Return True if obj is like Sequence[tuple[float, float]]
629
+ """
630
+
631
+ def is_numeric(obj) -> bool:
632
+ """
633
+ Return True if obj is a python or numpy float or integer
634
+ """
635
+ return isinstance(obj, (float, int, np.floating, np.integer))
636
+
637
+ if not iter(obj):
638
+ return False
639
+ try:
640
+ return all(is_numeric(a) and is_numeric(b) for a, b in obj)
641
+ except TypeError:
642
+ return False
613
643
 
614
644
 
615
645
  def has_groups(data: pd.DataFrame) -> bool:
@@ -396,7 +396,7 @@ class scale_continuous(
396
396
  scaled = [na_value if x == "nan" else x for x in scaled]
397
397
  else:
398
398
  scaled[pd.isna(scaled)] = na_value
399
- return scaled # pyright: ignore[reportReturnType]
399
+ return scaled
400
400
 
401
401
  def get_breaks(
402
402
  self, limits: Optional[tuple[float, float]] = None
@@ -206,7 +206,7 @@ class scale_discrete(
206
206
  pal = np.asarray(pal, dtype=object)
207
207
  idx = np.asarray(match(x, limits))
208
208
  try:
209
- pal_match = [pal[i] if i >= 0 else None for i in idx] # pyright: ignore[reportCallIssue,reportArgumentType]
209
+ pal_match = [pal[i] if i >= 0 else None for i in idx]
210
210
  except IndexError:
211
211
  # Deal with missing data
212
212
  # - Insert NaN where there is no match
@@ -155,7 +155,7 @@ def contour_lines(X, Y, Z, levels: int | FloatArrayLike):
155
155
  level_values = []
156
156
  start_pid = 1
157
157
  for level in levels:
158
- vertices, *_ = cgen.create_contour(level) # pyright: ignore[reportArgumentType]
158
+ vertices, *_ = cgen.create_contour(level)
159
159
  for pid, piece in enumerate(vertices, start=start_pid):
160
160
  n = len(piece) # pyright: ignore
161
161
  segments.append(piece)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plotnine
3
- Version: 0.15.0a3
3
+ Version: 0.15.0a5
4
4
  Summary: A Grammar of Graphics for Python
5
5
  Author-email: Hassan Kibirige <has2k1@gmail.com>
6
6
  License: The MIT License (MIT)
@@ -48,7 +48,7 @@ Requires-Dist: matplotlib>=3.8.0
48
48
  Requires-Dist: pandas>=2.2.0
49
49
  Requires-Dist: mizani~=0.14.0
50
50
  Requires-Dist: numpy>=1.23.5
51
- Requires-Dist: scipy>=1.8.0
51
+ Requires-Dist: scipy<1.16.0,>=1.8.0
52
52
  Requires-Dist: statsmodels>=0.14.0
53
53
  Provides-Extra: all
54
54
  Requires-Dist: plotnine[extra]; extra == "all"
@@ -1,12 +1,12 @@
1
1
  plotnine/__init__.py,sha256=HrJhd65bnny1t-TawUgvApVj4p-gDZ0ftpr2NKZeW_s,10316
2
2
  plotnine/animation.py,sha256=izJZ4Gy0cBHEBc8ehofsWSWOzZW8UEroy1Uvw86Igb0,7521
3
- plotnine/doctools.py,sha256=4qR1NCnnIG1Q-F0e2MeGzlhD9X0a00dOajtcl7m-yCQ,14546
3
+ plotnine/doctools.py,sha256=JBF55q1MX2fXYQcGDpVrGPdlKf5OiQ5gyTdWhnM_IzU,14558
4
4
  plotnine/exceptions.py,sha256=SgTxBHkV65HjGI3aFy2q1_lHP9HAdiuxVLN3U-PJWSQ,1616
5
5
  plotnine/ggplot.py,sha256=xFj9iWAyBvnhitCrpgdNonQIqqjBQ2aDgkqpvHbH364,24823
6
6
  plotnine/helpers.py,sha256=4R3KZmtGH46-kRNSGOA0JxZaLKBo0ge8Vnx1cDQ8_gI,966
7
7
  plotnine/iapi.py,sha256=jNLmUSoh5g9kNdhOoXSqNcqOdd2-6xdWAmst-YGU41U,9095
8
8
  plotnine/labels.py,sha256=3pOXth2Xma_qCqB_xXAGIkPQ9gcaUaaFEAsa5if1iR0,2830
9
- plotnine/layer.py,sha256=PHQbpfEK0GPXtDn87xC0J5HbKUb5_t9UYNtEyQaMYxE,16882
9
+ plotnine/layer.py,sha256=sUtzKTPnvkMuVFsNUFPkK9HUEcX7ohqv1EQV2KryS_c,16982
10
10
  plotnine/options.py,sha256=j3zXv4wc3J4nOI_TqJ5s_abuifodt_UN8MR8M4i8UVA,3108
11
11
  plotnine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  plotnine/qplot.py,sha256=BSAb4u5I7PaPGofkAgx7brdCNTjMZvC_TDGHVUZ35xM,7384
@@ -25,7 +25,7 @@ plotnine/_mpl/layout_manager/_engine.py,sha256=ESUvbLAlZApFbBi6w7gZA7S4guS0Rmrj-
25
25
  plotnine/_mpl/layout_manager/_layout_items.py,sha256=3XRBl7xEdBKdhrexRmnVe7k919po6nkyE0q5Hx7j5cQ,29642
26
26
  plotnine/_mpl/layout_manager/_layout_tree.py,sha256=O6U78CYOjSwS4lt56YF3YiOCXdxmV_oy3lYS4gMmzSc,26447
27
27
  plotnine/_mpl/layout_manager/_spaces.py,sha256=ahBpKt-q1kVOTGiGliwl_DNB6pTEekAzA_7-GXwFlBk,35789
28
- plotnine/_utils/__init__.py,sha256=pRCAZu_ux2uZtaJ_EZGDVFxITubGplo-3jqB7teE_KM,33239
28
+ plotnine/_utils/__init__.py,sha256=czHi-uv4eIBCDf6td11bGA41PMXaJ5j7t-avx_JbYgY,30636
29
29
  plotnine/_utils/context.py,sha256=HPQy_uyNXdS0s9URD7ZePyuc5hFU2XrRBLDTqRDLJzY,1708
30
30
  plotnine/_utils/dev.py,sha256=0qgRbMhcd4dfuLuYxx0skocKAtfwHF02ntyILRBogbg,1629
31
31
  plotnine/_utils/ipython.py,sha256=5Obr73xJ-4dzJEdBrFA8z9TXuxY7pIjKmzdTzWwnxNk,1884
@@ -66,10 +66,10 @@ plotnine/facets/labelling.py,sha256=JEuwERTK0IfmxTWHbl2nsGgxZ6xi0n2TTWT4_OSfQcQ,
66
66
  plotnine/facets/layout.py,sha256=TIkMChA0wJWLKN31PH0czS6CN4pw3o--PF49LakJ2h4,8967
67
67
  plotnine/facets/strips.py,sha256=-SWFaxqdzn-dnjx_Hxkuwd3kO-u_yreMLcMurm_IHqU,5688
68
68
  plotnine/geoms/__init__.py,sha256=HEfhNmmNH4xm4rpXnFRXY4eLkJha3XPM72IIwVjv5Lc,2697
69
- plotnine/geoms/annotate.py,sha256=Dqy5j29nrd7hHF-xZk8ZsE05j0ahdCtLkES7p7zjW-4,4025
69
+ plotnine/geoms/annotate.py,sha256=T5RxepV55HVNzPfkq43BWxduNIZPslRfPD1yx4bJtoo,4165
70
70
  plotnine/geoms/annotation_logticks.py,sha256=6iGdo5szck0_nXdHnvMaRMZuRbH8Tg87tJ_aan_frqg,8969
71
71
  plotnine/geoms/annotation_stripes.py,sha256=4Cw7TJ4SZChm_ioqfiiku0cPNnLruGuAP-4vyRao-9Y,6080
72
- plotnine/geoms/geom.py,sha256=Wa9DiHMQq-XznLcil6ho5QdCab6VhQtsqmGgDHUOCc0,16808
72
+ plotnine/geoms/geom.py,sha256=ayhBEoPc-9MLpu18HkwLoby4NIKC68ED4Pq0ioa4I9c,17687
73
73
  plotnine/geoms/geom_abline.py,sha256=6oxAJl_yFKKmf7OTHvACw6fg6kgJEN54hGKkyWOLr6o,3188
74
74
  plotnine/geoms/geom_area.py,sha256=wvQ4nNvhJNN3nfn6Bv1gCARC6IWTjOjOfHPfSmg6Sxc,818
75
75
  plotnine/geoms/geom_bar.py,sha256=SnqS4hPTfqXzdPh1U-kNuBg0LNX9_tQC9OKhIlB7cy0,1732
@@ -120,9 +120,10 @@ plotnine/guides/guide_colorbar.py,sha256=gL0218k3iJPNEpj6hWKxau3R8qRpT2bPkS1q9Pt
120
120
  plotnine/guides/guide_legend.py,sha256=CrcV3iCAcEfUnSbkGtsS31c3OFQMWKiHqZZXejxOdno,14212
121
121
  plotnine/guides/guides.py,sha256=cV7CwoYNrjkeaDHZ2AGcS2Dij5RpPovSiB-v47E7vhQ,15471
122
122
  plotnine/mapping/__init__.py,sha256=DLu9E0kwwuHxzTUenoVjCNTTdkWMwIDtkExLleBq1MI,205
123
+ plotnine/mapping/_atomic.py,sha256=TbobHVJlHRoSHibi6OOWMVM2J1r_kKQJMS6G5zvEhrg,4029
123
124
  plotnine/mapping/_env.py,sha256=ZXlTt2THRIcWb2WGk9fCpCMdVynlUX_BpG0Uwj7axi0,6072
124
125
  plotnine/mapping/_eval_environment.py,sha256=PTrnnqrxMXqjt23t2NGRcU9i8Jie3ZaMe6W5aKtI7bI,2502
125
- plotnine/mapping/aes.py,sha256=ZF69UUcA0IovFx2HMMKhVDnPxS9yw74LHL6C1VYwK84,15801
126
+ plotnine/mapping/aes.py,sha256=eqNTBHqFnSBPoVNdrUB7pYM-ShlUTYvmwdQRXh9beV4,16717
126
127
  plotnine/mapping/evaluation.py,sha256=kblTxVv3M4xIGnHyReUU0RtmmIN77Or2JBcci0nGGfE,5913
127
128
  plotnine/plot_composition/__init__.py,sha256=ZJYpfVF158cQZ1zREXy6wHNJ4FbSmqWxIkHWZwX3QT8,148
128
129
  plotnine/plot_composition/_compose.py,sha256=6UgXs6VBH0LIXW2uQlBQy-URh_mM948F5GOwN6IV734,12167
@@ -146,9 +147,9 @@ plotnine/scales/range.py,sha256=xBlFdAhthH1zKIJZDdkEyAA2kMZtyDorDFHKBMHKyAQ,1379
146
147
  plotnine/scales/scale.py,sha256=T7oMfiXA2xOL_LQQIEKY_06VvXVfF-norNpc2gdTNNw,8078
147
148
  plotnine/scales/scale_alpha.py,sha256=lYVZeaCC2pk-0-BoXnOeP0RdIbHYk6qo3DRClJrxTKo,2350
148
149
  plotnine/scales/scale_color.py,sha256=6Cyjxml8Jn3EFiDY8IGvYM9_qacHvBQZFvbFh5Gyg8Q,14514
149
- plotnine/scales/scale_continuous.py,sha256=-mYua-hXIZa2APJNygrNXtgzpsbmelwZLkjqKQgUq-Q,16537
150
+ plotnine/scales/scale_continuous.py,sha256=YMRjGh7QS644ajx5dVPJ9QTrWbTjmKt62MvVSFl3Y7U,16500
150
151
  plotnine/scales/scale_datetime.py,sha256=OM9gfHKGkQIBrgqCEE00zUV0cMXXxTIS7wc9dYQZ6sE,3983
151
- plotnine/scales/scale_discrete.py,sha256=lXlKA4sU61jrmgyvFFCVvjeVEG-FHgfDElPRzvK5jNE,9486
152
+ plotnine/scales/scale_discrete.py,sha256=UwAB0icMljH-eW6mK3g0YWAVzuE4P_91ZMYJhoMoMV4,9431
152
153
  plotnine/scales/scale_identity.py,sha256=-PL9vJn0C_wOgrOQpqYSQbTWFSALoRPFzGXzebABTv8,2211
153
154
  plotnine/scales/scale_linetype.py,sha256=pwLTmglN6d4bnChbuBi6HWbDP_nsE4viXD8CK6XKBPw,1373
154
155
  plotnine/scales/scale_manual.py,sha256=oMnIfQNfxO4qw-gkBG3ikyuXdeoMgstRSdiibLc_DAA,4525
@@ -169,7 +170,7 @@ plotnine/stats/stat_bindot.py,sha256=FS-Axqhb-nMR9HK77BD-ElDHpsS8NaJKLMIff4-lDSU
169
170
  plotnine/stats/stat_boxplot.py,sha256=5PvTTig5kAZQjenYL-158tjnzRnRUcnJpJL5qOdv9WI,5997
170
171
  plotnine/stats/stat_count.py,sha256=P560-9Lm6FWUvL5bGASIBxY3vQnbcZrU4CYlBdZpE3Y,1928
171
172
  plotnine/stats/stat_density.py,sha256=1TyOIiAaOaZesPcqIsnaVk14by0cKu6b7d7r-a5ZZSI,10346
172
- plotnine/stats/stat_density_2d.py,sha256=fRpsnR7MiYKTDAw0CngDp5LE5wDsulz_PyX3g57UZcw,5686
173
+ plotnine/stats/stat_density_2d.py,sha256=XSyE78IJwLLH4G5H7UD7ZrmknmaGCEMUHwvwNYmYVLQ,5647
173
174
  plotnine/stats/stat_ecdf.py,sha256=BdeisCWzDnuPMc3vBgZqpDsXCKy8ZfoSRwFPOQlgksM,1630
174
175
  plotnine/stats/stat_ellipse.py,sha256=NMr22TQMfVDZejIKvw1UWcB1NJptTlg6-qRf8d8EzJE,7570
175
176
  plotnine/stats/stat_function.py,sha256=AcP_wUu063fA8RAjc7AoFuVQmLdlsuEvP6m8AuTm9HY,3123
@@ -211,8 +212,8 @@ plotnine/themes/elements/element_line.py,sha256=xF6xW-iA66YEP_fN7ooqaYry8_8qZT-e
211
212
  plotnine/themes/elements/element_rect.py,sha256=w5cLH-Sr4cTRXVdkRiu8kBqFt3TXHhIb1MUITfi89gE,1767
212
213
  plotnine/themes/elements/element_text.py,sha256=8yhwBa9s9JKCtBcqcBNybbCGK6ieDnZv4SHiC4Sy2qc,6255
213
214
  plotnine/themes/elements/margin.py,sha256=jMHe-UKHHer_VYwAVDC-Tz2-AP_4YDuXPTWAuacoqgU,4080
214
- plotnine-0.15.0a3.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
215
- plotnine-0.15.0a3.dist-info/METADATA,sha256=E0dW-tEOB_1qHcqPrjENh9s63ew5YbVYgllwECO6_SI,9399
216
- plotnine-0.15.0a3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
217
- plotnine-0.15.0a3.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
218
- plotnine-0.15.0a3.dist-info/RECORD,,
215
+ plotnine-0.15.0a5.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
216
+ plotnine-0.15.0a5.dist-info/METADATA,sha256=HJHt2oWR1vudsK80OUWXBGCkU_d_Q6TWUlvo2d9w-nQ,9407
217
+ plotnine-0.15.0a5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
218
+ plotnine-0.15.0a5.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
219
+ plotnine-0.15.0a5.dist-info/RECORD,,