Skip to content

Commit

Permalink
Merge pull request #49 from hanjinliu/df-alpha
Browse files Browse the repository at this point in the history
Add `alpha` methods
  • Loading branch information
hanjinliu authored Apr 7, 2024
2 parents 404befe + abeac1f commit 68eb862
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 97 deletions.
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ lint.ignore = [
"S101", "S105", "S106", "S107",
# Ignore complexity
"C901", "PLR0911", "PLR0912", "PLR0913", "PLR0915", "PLW0603",
"ISC001",
]
lint.unfixable = [
# Don't touch unused imports
Expand Down Expand Up @@ -223,4 +224,5 @@ exclude_lines = [
"@overload",
"@abstractmethod",
"@deprecated",
"raise NotImplementedError",
]
29 changes: 15 additions & 14 deletions tests/test_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ def test_cat_plots(backend: str, orient: str):
"y": np.arange(30),
"label": np.repeat(["A", "B", "C"], 10),
"c": ["P", "Q"] * 15,
"val": np.cos(np.arange(30) / 10),
}
if orient == "v":
cat_plt = canvas.cat_x(df, "label", "y")
else:
cat_plt = canvas.cat_y(df, "y", "label")
cat_plt.add_stripplot(color="c").move(0.1)
cat_plt.add_swarmplot(color="c").move(0.1)
cat_plt.add_stripplot(color="c", alpha=0.8).move(0.1)
cat_plt.add_swarmplot(color="c", alpha="val").move(0.1)
cat_plt.add_boxplot(color="c").with_edge().with_outliers(ratio=0.5)
with filter_warning(backend, "plotly"):
box = cat_plt.add_boxplot(color="c").as_edge_only().move(0.1)
Expand Down Expand Up @@ -158,14 +159,14 @@ def test_agg(backend: str, orient: str):
cat_plt = canvas.cat_x(df, "label", "y")
else:
cat_plt = canvas.cat_y(df, "y", "label")
cat_plt.mean().add_line(color="c")
cat_plt.mean().add_markers(color="c")
cat_plt.mean().add_bars(color="c")
cat_plt.std().add_line(color="c")
cat_plt.sum().add_line(color="c")
cat_plt.median().add_line(color="c")
cat_plt.max().add_line(color="c")
cat_plt.min().add_line(color="c")
cat_plt.mean().add_line(color="c", alpha=0.8)
cat_plt.mean().add_markers(color="c", alpha=0.8)
cat_plt.mean().add_bars(color="c", alpha=0.8).as_edge_only()
cat_plt.std().add_line(color="c", width=2.5)
cat_plt.sum().add_line()
cat_plt.median().add_bars(color="c").update_width(1.5)
cat_plt.max().add_markers()
cat_plt.min().add_bars(color="c").update_hatch("/")
cat_plt.first().add_line(color="c")
if orient == "v":
canvas.cat_x(df, x="label").count().add_line(color="c")
Expand Down Expand Up @@ -204,10 +205,10 @@ def test_catx_legend(backend: str):
"label": np.repeat(["A", "B", "C"], 10),
}
_c = canvas.cat_x(df, "x", "y")
_c.add_boxplot(color="label")
_c.add_violinplot(color="label").with_rug()
_c.add_pointplot(color="label").err_by_se()
_c.add_barplot(color="label")
_c.add_boxplot(color="label", alpha=0.8)
_c.add_violinplot(color="label", alpha=0.8).with_rug()
_c.add_pointplot(color="label", alpha=0.8).err_by_se()
_c.add_barplot(color="label", alpha=0.8)
canvas.add_legend()

def test_marker_legend():
Expand Down
71 changes: 51 additions & 20 deletions whitecanvas/canvas/dataframe/_one_cat.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,14 @@ def __repr__(self) -> str:
return f"Aggregator<{self._method}>"

def __call__(self) -> OneAxisCatAggPlotter[_C, _DF]:
"""Aggregate the values before plotting it."""
"""
Aggregate the values before plotting it.
Examples
--------
Calculate mean of "value" for each "group" and connect them with lines.
>>> canvas.cat_x(df, "group", "value").mean().add_line()
"""
plotter = self._plotter
if plotter is None:
raise TypeError("Cannot call this method from a class.")
Expand Down Expand Up @@ -245,6 +252,7 @@ def add_violinplot(
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | None = None,
hatch: NStr | None = None,
dodge: NStr | bool = True,
extent: float = 0.8,
Expand All @@ -267,6 +275,8 @@ def add_violinplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float, optional
Opacity of the layer.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
dodge : str, sequence of str or bool, optional
Expand All @@ -288,14 +298,15 @@ def add_violinplot(
dodge=dodge, extent=extent, shape=shape, orient=self._orient,
backend=canvas._get_backend(),
) # fmt: skip
self._post_add_boxlike(layer, color)
self._post_add_boxlike(layer, color, alpha)
return canvas.add_layer(layer)

def add_boxplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | None = None,
hatch: NStr | None = None,
dodge: NStr | bool = True,
capsize: float = 0.1,
Expand All @@ -318,6 +329,8 @@ def add_boxplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float, optional
Opacity of the layer.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
dodge : str, sequence of str or bool, optional
Expand All @@ -339,14 +352,15 @@ def add_boxplot(
dodge=dodge, orient=self._orient, capsize=capsize, extent=extent,
backend=canvas._get_backend(),
) # fmt: skip
self._post_add_boxlike(layer, color)
self._post_add_boxlike(layer, color, alpha)
return canvas.add_layer(layer)

def add_pointplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | None = None,
hatch: NStr | None = None,
dodge: NStr | bool = True,
capsize: float = 0.1,
Expand Down Expand Up @@ -374,6 +388,8 @@ def add_pointplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float, optional
Opacity of the layer.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
dodge : str, sequence of str or bool, optional
Expand All @@ -393,14 +409,15 @@ def add_pointplot(
dodge=dodge, orient=self._orient, capsize=capsize,
backend=canvas._get_backend(),
) # fmt: skip
self._post_add_boxlike(layer, color)
self._post_add_boxlike(layer, color, alpha)
return canvas.add_layer(layer)

def add_barplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | None = None,
hatch: NStr | None = None,
dodge: NStr | bool = True,
capsize: float = 0.1,
Expand Down Expand Up @@ -429,6 +446,8 @@ def add_barplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float, optional
Opacity of the layer.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
dodge : str, sequence of str or bool, optional
Expand All @@ -450,21 +469,24 @@ def add_barplot(
dodge=dodge, orient=self._orient, capsize=capsize, extent=extent,
backend=canvas._get_backend(),
) # fmt: skip
self._post_add_boxlike(layer, color)
self._post_add_boxlike(layer, color, alpha)
return canvas.add_layer(layer)

def _post_add_boxlike(self, layer: _BoxLikeMixin, color):
def _post_add_boxlike(self, layer: _BoxLikeMixin, color, alpha):
canvas = self._canvas()
if color is not None and not layer._color_by.is_const():
layer.update_color_palette(canvas._color_palette)
elif color is None:
layer.update_const(color=canvas._color_palette.next())
if alpha is not None:
layer.update_const(alpha=alpha)

def add_stripplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | str | None = None,
hatch: NStr | None = None,
symbol: NStr | None = None,
size: str | None = None,
Expand All @@ -489,6 +511,8 @@ def add_stripplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float or str, optional
Opacity of the markers. If str, it must be a numerical column name.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
symbol : str or sequence of str, optional
Expand Down Expand Up @@ -526,33 +550,32 @@ def add_stripplot(
df, xj, yj, name=name, color=color, hatch=hatch, orient=self._orient,
symbol=symbol, size=size, backend=canvas._get_backend(),
) # fmt: skip
if color is not None and not layer._color_by.is_const():
layer.update_color(layer._color_by.by, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
layer._init_color_for_canvas(color, alpha, canvas)
return canvas.add_layer(layer)

def add_markers(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | str | None = None,
hatch: NStr | None = None,
symbol: NStr | None = None,
size: str | None = None,
dodge: NStr | bool = False,
) -> _lt.DFMarkerGroups[_DF]:
"""Alias of `add_stripplot` with no jittering."""
return self.add_stripplot(
color=color, hatch=hatch, symbol=symbol, size=size, dodge=dodge,
extent=0, seed=0, name=name,
color=color, alpha=alpha, hatch=hatch, symbol=symbol, size=size,
dodge=dodge, extent=0, seed=0, name=name,
) # fmt: skip

def add_swarmplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | str | None = None,
hatch: NStr | None = None,
symbol: NStr | None = None,
size: str | None = None,
Expand All @@ -577,6 +600,8 @@ def add_swarmplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float or str, optional
Opacity of the markers. If str, it must be a numerical column name.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
symbol : str or sequence of str, optional
Expand Down Expand Up @@ -618,17 +643,15 @@ def add_swarmplot(
df, xj, yj, name=name, color=color, hatch=hatch, orient=self._orient,
symbol=symbol, size=size, backend=canvas._get_backend(),
) # fmt: skip
if color is not None and not layer._color_by.is_const():
layer.update_color(layer._color_by.by, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
layer._init_color_for_canvas(color, alpha, canvas)
return canvas.add_layer(layer)

def add_rugplot(
self,
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | str | None = None,
width: float | None = None,
style: NStr | None = None,
dodge: NStr | bool = True,
Expand All @@ -651,6 +674,8 @@ def add_rugplot(
Name of the layer.
color : str or sequence of str, optional
Column name(s) for coloring the lines. Must be categorical.
alpha : float or str, optional
Opacity of the markers. If str, it must be a numerical column name.
hatch : str or sequence of str, optional
Column name(s) for hatches. Must be categorical.
symbol : str or sequence of str, optional
Expand Down Expand Up @@ -684,10 +709,7 @@ def add_rugplot(
df, jitter, self._get_value(), name=name, color=color, orient=self._orient,
extent=_extent, width=width, style=style, backend=canvas._get_backend(),
) # fmt: skip
if color is not None and not layer._color_by.is_const():
layer.update_color(layer._color_by.by, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
layer._init_color_for_canvas(color, alpha, canvas)
return canvas.add_layer(layer)

def add_heatmap_hist(
Expand Down Expand Up @@ -775,6 +797,7 @@ def add_line(
*,
name: str | None = None,
color: NStr | None = None,
alpha: float | None = None,
width: float | None = None,
style: NStr | None = None,
dodge: NStr | bool = False,
Expand Down Expand Up @@ -821,13 +844,16 @@ def add_line(
layer.update_color(color, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
if alpha is not None:
layer.update_alpha(alpha)
return canvas.add_layer(layer)

def add_markers(
self,
*,
name: str | None = None,
color: NStr | ColorType | None = None,
alpha: float | None = None,
hatch: NStr | Hatch | None = None,
size: str | float | None = None,
symbol: NStr | Symbol | None = None,
Expand Down Expand Up @@ -880,13 +906,16 @@ def add_markers(
layer.update_color(color, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
if alpha is not None:
layer.update_alpha(alpha)
return canvas.add_layer(layer)

def add_bars(
self,
*,
name: str | None = None,
color: NStr | ColorType | None = None,
alpha: float | None = None,
hatch: NStr | Hatch | None = None,
extent: float = 0.8,
dodge: NStr | bool = True,
Expand Down Expand Up @@ -938,6 +967,8 @@ def add_bars(
layer.update_color(color, palette=canvas._color_palette)
elif color is None:
layer.update_color(canvas._color_palette.next())
if alpha is not None:
layer.update_alpha(alpha)
return canvas.add_layer(layer)

def _aggregate(
Expand Down
6 changes: 6 additions & 0 deletions whitecanvas/layers/_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,12 @@ def width(self) -> float:

@width.setter
def width(self, value: float):
if not is_real_number(value):
raise ValueError(
"Width must be a real number for a constant-edge layer. If you want to "
"set multiple width values, use `with_edge_multi` method to convert "
"the layer to a multi-edge layer."
)
if value < 0:
raise ValueError(f"Edge width must be non-negative, got {value!r}")
value = float(value)
Expand Down
Loading

0 comments on commit 68eb862

Please sign in to comment.