plotnine 0.15.0a3__py3-none-any.whl → 0.15.0a4__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
@@ -7,13 +7,12 @@ from itertools import chain, repeat
7
7
 
8
8
  from .._utils import (
9
9
  data_mapping_as_kwargs,
10
- is_list_like,
11
10
  remove_missing,
12
11
  )
13
12
  from .._utils.registry import Register, Registry
14
13
  from ..exceptions import PlotnineError
15
14
  from ..layer import layer
16
- from ..mapping.aes import is_valid_aesthetic, rename_aesthetics
15
+ from ..mapping.aes import RepeatAesthetic, rename_aesthetics
17
16
  from ..mapping.evaluation import evaluate
18
17
  from ..positions.position import position
19
18
  from ..stats.stat import stat
@@ -179,11 +178,16 @@ class geom(ABC, metaclass=Register):
179
178
  ----------
180
179
  data :
181
180
  Data
181
+ """
182
182
 
183
- Returns
184
- -------
185
- out :
186
- Parameters used by the geoms.
183
+ def setup_aes_params(self, data: pd.DataFrame):
184
+ """
185
+ Override this method to verify and/or adjust aesthetic parameters
186
+
187
+ Parameters
188
+ ----------
189
+ data :
190
+ Data
187
191
  """
188
192
 
189
193
  def setup_data(self, data: pd.DataFrame) -> pd.DataFrame:
@@ -255,23 +259,28 @@ class geom(ABC, metaclass=Register):
255
259
  data[ae] = evaled[ae]
256
260
 
257
261
  num_panels = len(data["PANEL"].unique()) if "PANEL" in data else 1
262
+ across_panels = num_panels > 1 and not self.params["inherit_aes"]
258
263
 
259
264
  # Aesthetics set as parameters to the geom/stat
260
265
  for ae, value in self.aes_params.items():
261
266
  try:
262
267
  data[ae] = value
263
268
  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)))
269
+ # NOTE: Handling of the edgecases in this exception is not
270
+ # foolproof.
271
+ repeat_ae = getattr(RepeatAesthetic, ae, None)
272
+ if across_panels:
273
+ # Adding an annotation/abline/hline/vhline with multiple
274
+ # items across to more than 1 panel
275
+ value = list(chain(*repeat(value, num_panels)))
276
+ data[ae] = value
277
+ elif repeat_ae:
278
+ # Some aesthetics may have valid values that are not
279
+ # scalar. e.g. sequences. For such case, we need to
280
+ # insert a sequence of the same value.
281
+ data[ae] = repeat_ae(value, len(data))
270
282
  else:
271
- msg = (
272
- f"'{value}' does not look like a "
273
- f"valid value for `{ae}`"
274
- )
283
+ msg = f"'{ae}={value}' does not look like a valid value"
275
284
  raise PlotnineError(msg) from e
276
285
 
277
286
  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(
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.0a4
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=cjxzWTZiAMop9FuXWg5kqgo1lBEG2Uu6DzARjHOpBY4,17300
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
@@ -122,7 +122,7 @@ plotnine/guides/guides.py,sha256=cV7CwoYNrjkeaDHZ2AGcS2Dij5RpPovSiB-v47E7vhQ,154
122
122
  plotnine/mapping/__init__.py,sha256=DLu9E0kwwuHxzTUenoVjCNTTdkWMwIDtkExLleBq1MI,205
123
123
  plotnine/mapping/_env.py,sha256=ZXlTt2THRIcWb2WGk9fCpCMdVynlUX_BpG0Uwj7axi0,6072
124
124
  plotnine/mapping/_eval_environment.py,sha256=PTrnnqrxMXqjt23t2NGRcU9i8Jie3ZaMe6W5aKtI7bI,2502
125
- plotnine/mapping/aes.py,sha256=ZF69UUcA0IovFx2HMMKhVDnPxS9yw74LHL6C1VYwK84,15801
125
+ plotnine/mapping/aes.py,sha256=eqNTBHqFnSBPoVNdrUB7pYM-ShlUTYvmwdQRXh9beV4,16717
126
126
  plotnine/mapping/evaluation.py,sha256=kblTxVv3M4xIGnHyReUU0RtmmIN77Or2JBcci0nGGfE,5913
127
127
  plotnine/plot_composition/__init__.py,sha256=ZJYpfVF158cQZ1zREXy6wHNJ4FbSmqWxIkHWZwX3QT8,148
128
128
  plotnine/plot_composition/_compose.py,sha256=6UgXs6VBH0LIXW2uQlBQy-URh_mM948F5GOwN6IV734,12167
@@ -146,9 +146,9 @@ plotnine/scales/range.py,sha256=xBlFdAhthH1zKIJZDdkEyAA2kMZtyDorDFHKBMHKyAQ,1379
146
146
  plotnine/scales/scale.py,sha256=T7oMfiXA2xOL_LQQIEKY_06VvXVfF-norNpc2gdTNNw,8078
147
147
  plotnine/scales/scale_alpha.py,sha256=lYVZeaCC2pk-0-BoXnOeP0RdIbHYk6qo3DRClJrxTKo,2350
148
148
  plotnine/scales/scale_color.py,sha256=6Cyjxml8Jn3EFiDY8IGvYM9_qacHvBQZFvbFh5Gyg8Q,14514
149
- plotnine/scales/scale_continuous.py,sha256=-mYua-hXIZa2APJNygrNXtgzpsbmelwZLkjqKQgUq-Q,16537
149
+ plotnine/scales/scale_continuous.py,sha256=YMRjGh7QS644ajx5dVPJ9QTrWbTjmKt62MvVSFl3Y7U,16500
150
150
  plotnine/scales/scale_datetime.py,sha256=OM9gfHKGkQIBrgqCEE00zUV0cMXXxTIS7wc9dYQZ6sE,3983
151
- plotnine/scales/scale_discrete.py,sha256=lXlKA4sU61jrmgyvFFCVvjeVEG-FHgfDElPRzvK5jNE,9486
151
+ plotnine/scales/scale_discrete.py,sha256=UwAB0icMljH-eW6mK3g0YWAVzuE4P_91ZMYJhoMoMV4,9431
152
152
  plotnine/scales/scale_identity.py,sha256=-PL9vJn0C_wOgrOQpqYSQbTWFSALoRPFzGXzebABTv8,2211
153
153
  plotnine/scales/scale_linetype.py,sha256=pwLTmglN6d4bnChbuBi6HWbDP_nsE4viXD8CK6XKBPw,1373
154
154
  plotnine/scales/scale_manual.py,sha256=oMnIfQNfxO4qw-gkBG3ikyuXdeoMgstRSdiibLc_DAA,4525
@@ -169,7 +169,7 @@ plotnine/stats/stat_bindot.py,sha256=FS-Axqhb-nMR9HK77BD-ElDHpsS8NaJKLMIff4-lDSU
169
169
  plotnine/stats/stat_boxplot.py,sha256=5PvTTig5kAZQjenYL-158tjnzRnRUcnJpJL5qOdv9WI,5997
170
170
  plotnine/stats/stat_count.py,sha256=P560-9Lm6FWUvL5bGASIBxY3vQnbcZrU4CYlBdZpE3Y,1928
171
171
  plotnine/stats/stat_density.py,sha256=1TyOIiAaOaZesPcqIsnaVk14by0cKu6b7d7r-a5ZZSI,10346
172
- plotnine/stats/stat_density_2d.py,sha256=fRpsnR7MiYKTDAw0CngDp5LE5wDsulz_PyX3g57UZcw,5686
172
+ plotnine/stats/stat_density_2d.py,sha256=XSyE78IJwLLH4G5H7UD7ZrmknmaGCEMUHwvwNYmYVLQ,5647
173
173
  plotnine/stats/stat_ecdf.py,sha256=BdeisCWzDnuPMc3vBgZqpDsXCKy8ZfoSRwFPOQlgksM,1630
174
174
  plotnine/stats/stat_ellipse.py,sha256=NMr22TQMfVDZejIKvw1UWcB1NJptTlg6-qRf8d8EzJE,7570
175
175
  plotnine/stats/stat_function.py,sha256=AcP_wUu063fA8RAjc7AoFuVQmLdlsuEvP6m8AuTm9HY,3123
@@ -211,8 +211,8 @@ plotnine/themes/elements/element_line.py,sha256=xF6xW-iA66YEP_fN7ooqaYry8_8qZT-e
211
211
  plotnine/themes/elements/element_rect.py,sha256=w5cLH-Sr4cTRXVdkRiu8kBqFt3TXHhIb1MUITfi89gE,1767
212
212
  plotnine/themes/elements/element_text.py,sha256=8yhwBa9s9JKCtBcqcBNybbCGK6ieDnZv4SHiC4Sy2qc,6255
213
213
  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,,
214
+ plotnine-0.15.0a4.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
215
+ plotnine-0.15.0a4.dist-info/METADATA,sha256=MCVzMIfRSdwYyq2UrgdS74Zc8QiMo9pp8GiwCVFZXCo,9407
216
+ plotnine-0.15.0a4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
217
+ plotnine-0.15.0a4.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
218
+ plotnine-0.15.0a4.dist-info/RECORD,,