This is an automated email from the ASF dual-hosted git repository.
michaelsmolina pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new ffe9244458 fix: Decimal values for Histogram bins (#32253)
ffe9244458 is described below
commit ffe9244458d03995b760638e9bb5b347c0cc68d6
Author: Michael S. Molina <[email protected]>
AuthorDate: Fri Feb 14 09:04:23 2025 -0300
fix: Decimal values for Histogram bins (#32253)
---
.../src/sections/chartTitle.tsx | 2 +-
.../src/Histogram/controlPanel.tsx | 57 +++++++++++++++++++++-
.../src/Histogram/transformProps.ts | 37 +++++++++-----
.../plugin-chart-echarts/src/Histogram/types.ts | 2 +
superset/utils/pandas_postprocessing/histogram.py | 3 +-
.../pandas_postprocessing/test_histogram.py | 48 ++++++++++--------
6 files changed, 112 insertions(+), 37 deletions(-)
diff --git
a/superset-frontend/packages/superset-ui-chart-controls/src/sections/chartTitle.tsx
b/superset-frontend/packages/superset-ui-chart-controls/src/sections/chartTitle.tsx
index e8cda4991f..6c8d08364c 100644
---
a/superset-frontend/packages/superset-ui-chart-controls/src/sections/chartTitle.tsx
+++
b/superset-frontend/packages/superset-ui-chart-controls/src/sections/chartTitle.tsx
@@ -54,7 +54,7 @@ export const titleControls: ControlPanelSectionConfig = {
type: 'SelectControl',
freeForm: true,
clearable: true,
- label: t('X AXIS TITLE BOTTOM MARGIN'),
+ label: t('X Axis Title Margin'),
renderTrigger: true,
default: TITLE_MARGIN_OPTIONS[0],
choices: formatSelectOptions(TITLE_MARGIN_OPTIONS),
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/controlPanel.tsx
b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/controlPanel.tsx
index a347694f1b..d4e8d4b86d 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/controlPanel.tsx
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/controlPanel.tsx
@@ -27,7 +27,9 @@ import {
formatSelectOptionsForRange,
dndGroupByControl,
columnsByType,
- sections,
+ D3_FORMAT_OPTIONS,
+ D3_FORMAT_DOCS,
+ D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT,
} from '@superset-ui/chart-controls';
import { showLegendControl, showValueControl } from '../controls';
@@ -105,7 +107,6 @@ const config: ControlPanelConfig = {
],
],
},
- sections.titleControls,
{
label: t('Chart Options'),
expanded: true,
@@ -113,6 +114,58 @@ const config: ControlPanelConfig = {
['color_scheme'],
[showValueControl],
[showLegendControl],
+ [
+ {
+ name: 'x_axis_title',
+ config: {
+ type: 'TextControl',
+ label: t('X Axis Title'),
+ renderTrigger: true,
+ default: '',
+ description: t('Changing this control takes effect instantly'),
+ },
+ },
+ ],
+ [
+ {
+ name: 'x_axis_format',
+ config: {
+ type: 'SelectControl',
+ freeForm: true,
+ label: t('X Axis Format'),
+ renderTrigger: true,
+ default: 'SMART_NUMBER',
+ choices: D3_FORMAT_OPTIONS,
+ description: `${D3_FORMAT_DOCS}
${D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT}`,
+ },
+ },
+ ],
+ [
+ {
+ name: 'y_axis_title',
+ config: {
+ type: 'TextControl',
+ label: t('Y Axis Title'),
+ renderTrigger: true,
+ default: '',
+ description: t('Changing this control takes effect instantly'),
+ },
+ },
+ ],
+ [
+ {
+ name: 'y_axis_format',
+ config: {
+ type: 'SelectControl',
+ freeForm: true,
+ label: t('Y Axis Format'),
+ renderTrigger: true,
+ default: 'SMART_NUMBER',
+ choices: D3_FORMAT_OPTIONS,
+ description: `${D3_FORMAT_DOCS}
${D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT}`,
+ },
+ },
+ ],
],
},
],
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/transformProps.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/transformProps.ts
index df8fe3b156..388e79ae94 100644
---
a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/transformProps.ts
+++
b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/transformProps.ts
@@ -25,7 +25,7 @@ import {
CategoricalColorNamespace,
NumberFormats,
getColumnLabel,
- getNumberFormatter,
+ getValueFormatter,
tooltipHtml,
} from '@superset-ui/core';
import { HistogramChartProps, HistogramTransformedProps } from './types';
@@ -41,6 +41,7 @@ export default function transformProps(
const refs: Refs = {};
let focusedSeries: number | undefined;
const {
+ datasource: { currencyFormats = {}, columnFormats = {} },
formData,
height,
hooks,
@@ -58,19 +59,33 @@ export default function transformProps(
showLegend,
showValue,
sliceId,
+ xAxisFormat,
xAxisTitle,
yAxisTitle,
+ yAxisFormat,
} = formData;
const { data } = queriesData[0];
const colorFn = CategoricalColorNamespace.getScale(colorScheme);
- const formatter = getNumberFormatter(
- normalize ? NumberFormats.FLOAT_2_POINT : NumberFormats.INTEGER,
- );
+
+ const formatter = (format: string) =>
+ getValueFormatter(
+ column,
+ currencyFormats,
+ columnFormats,
+ format,
+ undefined,
+ );
+ const xAxisFormatter = formatter(xAxisFormat);
+ const yAxisFormatter = formatter(yAxisFormat);
+
const percentFormatter = getPercentFormatter(NumberFormats.PERCENT_2_POINT);
const groupbySet = new Set(groupby);
- const xAxisData: string[] = Object.keys(data[0]).filter(
- key => !groupbySet.has(key),
- );
+ const xAxisData: string[] = Object.keys(data[0])
+ .filter(key => !groupbySet.has(key))
+ .map(key => {
+ const array = key.split(' - ').map(value => parseFloat(value));
+ return `${xAxisFormatter(array[0])} '-' ${xAxisFormatter(array[1])}`;
+ });
const barSeries: BarSeriesOption[] = data.map(datum => {
const seriesName =
groupby.length > 0
@@ -91,7 +106,7 @@ export default function transformProps(
position: 'top',
formatter: params => {
const { value } = params;
- return formatter.format(value as number);
+ return yAxisFormatter.format(value as number);
},
},
};
@@ -108,7 +123,7 @@ export default function transformProps(
const title = params[0].name;
const rows = params.map(param => {
const { marker, seriesName, value } = param;
- return [`${marker}${seriesName}`, formatter.format(value as number)];
+ return [`${marker}${seriesName}`, yAxisFormatter.format(value as
number)];
});
if (groupby.length > 0) {
const total = params.reduce(
@@ -122,7 +137,7 @@ export default function transformProps(
),
);
}
- const totalRow = ['Total', formatter.format(total)];
+ const totalRow = ['Total', yAxisFormatter.format(total)];
if (!normalize) {
totalRow.push(percentFormatter.format(1));
}
@@ -159,7 +174,7 @@ export default function transformProps(
type: 'value',
nameLocation: 'middle',
axisLabel: {
- formatter: (value: number) => formatter.format(value),
+ formatter: (value: number) => yAxisFormatter.format(value),
},
},
series: barSeries,
diff --git
a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/types.ts
b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/types.ts
index ca6c16d79e..ab3d4b75c2 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/types.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/Histogram/types.ts
@@ -28,7 +28,9 @@ export type HistogramFormData = QueryFormData & {
sliceId: number;
showLegend: boolean;
showValue: boolean;
+ xAxisFormat: string;
xAxisTitle: string;
+ yAxisFormat: string;
yAxisTitle: string;
};
diff --git a/superset/utils/pandas_postprocessing/histogram.py
b/superset/utils/pandas_postprocessing/histogram.py
index f55f0d0762..8ef9abadc7 100644
--- a/superset/utils/pandas_postprocessing/histogram.py
+++ b/superset/utils/pandas_postprocessing/histogram.py
@@ -60,8 +60,7 @@ def histogram(
# convert the bin edges to strings
bin_edges_str = [
- f"{int(bin_edges[i])} - {int(bin_edges[i+1])}"
- for i in range(len(bin_edges) - 1)
+ f"{bin_edges[i]} - {bin_edges[i+1]}" for i in range(len(bin_edges) - 1)
]
def hist_values(series: Series) -> np.ndarray:
diff --git a/tests/unit_tests/pandas_postprocessing/test_histogram.py
b/tests/unit_tests/pandas_postprocessing/test_histogram.py
index ee0261a9fa..9246a06df0 100644
--- a/tests/unit_tests/pandas_postprocessing/test_histogram.py
+++ b/tests/unit_tests/pandas_postprocessing/test_histogram.py
@@ -35,7 +35,13 @@ def test_histogram_no_groupby():
)
result = histogram(data_with_no_groupings, "a", [], bins)
assert result.shape == (1, bins)
- assert result.columns.tolist() == ["1 - 2", "2 - 4", "4 - 6", "6 - 8", "8
- 10"]
+ assert result.columns.tolist() == [
+ "1.0 - 2.8",
+ "2.8 - 4.6",
+ "4.6 - 6.4",
+ "6.4 - 8.2",
+ "8.2 - 10.0",
+ ]
assert result.values.tolist() == [[2, 2, 2, 2, 2]]
@@ -44,11 +50,11 @@ def test_histogram_with_groupby():
assert result.shape == (2, bins + 1)
assert result.columns.tolist() == [
"group",
- "1 - 2",
- "2 - 4",
- "4 - 6",
- "6 - 8",
- "8 - 10",
+ "1.0 - 2.8",
+ "2.8 - 4.6",
+ "4.6 - 6.4",
+ "6.4 - 8.2",
+ "8.2 - 10.0",
]
assert result.values.tolist() == [["A", 2, 0, 2, 0, 2], ["B", 0, 2, 0, 2,
0]]
@@ -58,11 +64,11 @@ def test_histogram_with_groupby_and_normalize():
assert result.shape == (2, bins + 1)
assert result.columns.tolist() == [
"group",
- "1 - 2",
- "2 - 4",
- "4 - 6",
- "6 - 8",
- "8 - 10",
+ "1.0 - 2.8",
+ "2.8 - 4.6",
+ "4.6 - 6.4",
+ "6.4 - 8.2",
+ "8.2 - 10.0",
]
assert result.values.tolist() == [
["A", 0.2, 0.0, 0.2, 0.0, 0.2],
@@ -75,11 +81,11 @@ def test_histogram_with_groupby_and_cumulative():
assert result.shape == (2, bins + 1)
assert result.columns.tolist() == [
"group",
- "1 - 2",
- "2 - 4",
- "4 - 6",
- "6 - 8",
- "8 - 10",
+ "1.0 - 2.8",
+ "2.8 - 4.6",
+ "4.6 - 6.4",
+ "6.4 - 8.2",
+ "8.2 - 10.0",
]
assert result.values.tolist() == [["A", 2, 2, 4, 4, 6], ["B", 0, 2, 2, 4,
4]]
@@ -89,11 +95,11 @@ def
test_histogram_with_groupby_and_cumulative_and_normalize():
assert result.shape == (2, bins + 1)
assert result.columns.tolist() == [
"group",
- "1 - 2",
- "2 - 4",
- "4 - 6",
- "6 - 8",
- "8 - 10",
+ "1.0 - 2.8",
+ "2.8 - 4.6",
+ "4.6 - 6.4",
+ "6.4 - 8.2",
+ "8.2 - 10.0",
]
assert result.values.tolist() == [
[