Skip to content

Commit

Permalink
fix: Remove frequency_bar (deephaven#955)
Browse files Browse the repository at this point in the history
Fixes deephaven#66 

BREAKING: frequency_bar is deprecated. Instead, only pass one
of x or y into bar.
  • Loading branch information
jnumainville authored Oct 25, 2024
1 parent 0ac72be commit 17fbfca
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 1 deletion.
15 changes: 15 additions & 0 deletions plugins/plotly-express/docs/bar.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ bar_plot_smoke = dx.bar(sorted_tips, x="Day", y="TotalBill", by="Smoker")
bar_plot_sex = dx.bar(sorted_tips, x="Day", y="TotalBill", by="Sex")
```

### Frequency of categories

Visualize the frequency of categories in a column by passing to either the `x` or `y` argument.

```python
import deephaven.plot.express as dx
tips = dx.data.tips()

# count the number of occurrences of each day with a vertical bar plot
bar_plot_vertical = dx.bar(tips, x="Day")

# count the number of occurrences of each day with a horizontal bar plot
bar_plot_horizontal = dx.bar(tips, y="Day")
```

## API Reference
```{eval-rst}
.. dhautofunction:: deephaven.plot.express.bar
Expand Down
16 changes: 15 additions & 1 deletion plugins/plotly-express/src/deephaven/plot/express/plots/bar.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

from typing import Callable
import warnings

from plotly import express as px

Expand Down Expand Up @@ -55,7 +56,9 @@ def bar(
Args:
table: A table to pull data from.
x: A column or list of columns that contain x-axis values.
If only x is specified, the y-axis values are the count of each unique x value.
y: A column or list of columns that contain y-axis values.
If only y is specified, the x-axis values are the count of each unique y value.
by: A column or list of columns that contain values to plot the figure traces by.
All values or combination of values map to a unique design. The variable
by_vars specifies which design elements are used.
Expand Down Expand Up @@ -144,7 +147,12 @@ def bar(
"""
args = locals()

return process_args(args, {"bar", "supports_lists"}, px_func=px.bar)
groups = {"bar", "supports_lists"}

if not x or not y:
groups.add("preprocess_freq")

return process_args(args, groups, px_func=px.bar)


def _bar_polar(
Expand Down Expand Up @@ -386,6 +394,12 @@ def frequency_bar(
DeephavenFigure: A DeephavenFigure that contains the bar chart
"""
warnings.warn(
"This function is deprecated and will be removed in a future release. "
"Use bar with only one of x or y specified instead for identical behavior.",
DeprecationWarning,
stacklevel=2,
)

if x and y:
raise ValueError("Cannot specify both x and y")
Expand Down
217 changes: 217 additions & 0 deletions plugins/plotly-express/test/deephaven/plot/express/plots/test_bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import unittest

from ..BaseTest import BaseTestCase


class BarTestCase(BaseTestCase):
def setUp(self) -> None:
from deephaven import new_table
from deephaven.column import int_col

self.source = new_table(
[
int_col("X", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("X2", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("Y", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("Y2", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("size", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("text", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("hover_name", [1, 2, 2, 3, 3, 3, 4, 4, 5]),
int_col("category", [1, 2, 1, 2, 1, 2, 1, 2, 1]),
]
)

def test_basic_bar_x(self):
import src.deephaven.plot.express as dx
from deephaven.constants import NULL_LONG, NULL_INT

chart = dx.bar(self.source, x="X").to_dict(self.exporter)
plotly, deephaven = chart["plotly"], chart["deephaven"]

# pop template as we currently do not modify it
plotly["layout"].pop("template")

expected_data = [
{
"alignmentgroup": "True",
"hovertemplate": "X=%{x}<br>count=%{y}<extra></extra>",
"legendgroup": "",
"marker": {"color": "#636efa", "pattern": {"shape": ""}},
"name": "",
"offsetgroup": "",
"orientation": "v",
"showlegend": False,
"textposition": "auto",
"type": "bar",
"x": [NULL_INT],
"xaxis": "x",
"y": [NULL_LONG],
"yaxis": "y",
}
]

self.assertEqual(plotly["data"], expected_data)

expected_layout = {
"barmode": "relative",
"legend": {"tracegroupgap": 0},
"margin": {"t": 60},
"xaxis": {
"anchor": "y",
"domain": [0.0, 1.0],
"side": "bottom",
"title": {"text": "X"},
},
"yaxis": {
"anchor": "x",
"domain": [0.0, 1.0],
"side": "left",
"title": {"text": "count"},
},
}

self.assertEqual(plotly["layout"], expected_layout)

expected_mappings = [
{
"data_columns": {
"X": ["/plotly/data/0/x"],
"count": ["/plotly/data/0/y"],
},
"table": 0,
}
]

self.assertEqual(deephaven["mappings"], expected_mappings)

self.assertEqual(deephaven["is_user_set_template"], False)
self.assertEqual(deephaven["is_user_set_color"], False)

def test_basic_bar_y(self):
import src.deephaven.plot.express as dx
from deephaven.constants import NULL_LONG, NULL_INT

chart = dx.bar(self.source, y="Y").to_dict(self.exporter)
plotly, deephaven = chart["plotly"], chart["deephaven"]

# pop template as we currently do not modify it
plotly["layout"].pop("template")

expected_data = [
{
"alignmentgroup": "True",
"hovertemplate": "count=%{x}<br>Y=%{y}<extra></extra>",
"legendgroup": "",
"marker": {"color": "#636efa", "pattern": {"shape": ""}},
"name": "",
"offsetgroup": "",
"orientation": "h",
"showlegend": False,
"textposition": "auto",
"type": "bar",
"x": [NULL_LONG],
"xaxis": "x",
"y": [NULL_INT],
"yaxis": "y",
}
]

self.assertEqual(plotly["data"], expected_data)

expected_layout = {
"barmode": "relative",
"legend": {"tracegroupgap": 0},
"margin": {"t": 60},
"xaxis": {
"anchor": "y",
"domain": [0.0, 1.0],
"side": "bottom",
"title": {"text": "count"},
},
"yaxis": {
"anchor": "x",
"domain": [0.0, 1.0],
"side": "left",
"title": {"text": "Y"},
},
}

self.assertEqual(plotly["layout"], expected_layout)

expected_mappings = [
{
"data_columns": {
"Y": ["/plotly/data/0/y"],
"count": ["/plotly/data/0/x"],
},
"table": 0,
}
]

self.assertEqual(deephaven["mappings"], expected_mappings)

self.assertEqual(deephaven["is_user_set_template"], False)
self.assertEqual(deephaven["is_user_set_color"], False)

def test_basic_bar_x_y(self):
import src.deephaven.plot.express as dx
from deephaven.constants import NULL_INT

chart = dx.bar(self.source, x="X", y="Y").to_dict(self.exporter)
plotly, deephaven = chart["plotly"], chart["deephaven"]

# pop template as we currently do not modify it
plotly["layout"].pop("template")

expected_data = [
{
"alignmentgroup": "True",
"hovertemplate": "X=%{x}<br>Y=%{y}<extra></extra>",
"legendgroup": "",
"marker": {"color": "#636efa", "pattern": {"shape": ""}},
"name": "",
"offsetgroup": "",
"orientation": "v",
"showlegend": False,
"textposition": "auto",
"type": "bar",
"x": [NULL_INT],
"xaxis": "x",
"y": [NULL_INT],
"yaxis": "y",
}
]

self.assertEqual(plotly["data"], expected_data)

expected_layout = {
"barmode": "relative",
"legend": {"tracegroupgap": 0},
"margin": {"t": 60},
"xaxis": {
"anchor": "y",
"domain": [0.0, 1.0],
"side": "bottom",
"title": {"text": "X"},
},
"yaxis": {
"anchor": "x",
"domain": [0.0, 1.0],
"side": "left",
"title": {"text": "Y"},
},
}

self.assertEqual(plotly["layout"], expected_layout)

expected_mappings = [
{
"data_columns": {"X": ["/plotly/data/0/x"], "Y": ["/plotly/data/0/y"]},
"table": 0,
}
]

self.assertEqual(deephaven["mappings"], expected_mappings)

self.assertEqual(deephaven["is_user_set_template"], False)
self.assertEqual(deephaven["is_user_set_color"], False)

0 comments on commit 17fbfca

Please sign in to comment.