You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by jl...@apache.org on 2026/06/09 17:28:40 UTC
(superset) branch master updated: fix: use pd.to_numeric in df_metrics_to_num to handle string-encoded numerics from ClickHouse (#40190)
This is an automated email from the ASF dual-hosted git repository.
sadpandajoe 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 6311e2c315e fix: use pd.to_numeric in df_metrics_to_num to handle string-encoded numerics from ClickHouse (#40190)
6311e2c315e is described below
commit 6311e2c315e3c45e8b1f527598531b16be83b430
Author: EMMANUELA OPURUM <86...@users.noreply.github.com>
AuthorDate: Tue Jun 9 18:28:34 2026 +0100
fix: use pd.to_numeric in df_metrics_to_num to handle string-encoded numerics from ClickHouse (#40190)
Co-authored-by: Emmanuela Opurum <yo...@example.com>
Co-authored-by: Đỗ Trọng Hải <41...@users.noreply.github.com>
---
superset/common/utils/dataframe_utils.py | 10 +++++++---
tests/unit_tests/common/test_dataframe_utils.py | 25 +++++++++++++++++++++++++
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/superset/common/utils/dataframe_utils.py b/superset/common/utils/dataframe_utils.py
index 89563dec06f..82f01502f83 100644
--- a/superset/common/utils/dataframe_utils.py
+++ b/superset/common/utils/dataframe_utils.py
@@ -55,9 +55,13 @@ def df_metrics_to_num(df: pd.DataFrame, query_object: QueryObject) -> None:
"""Converting metrics to numeric when pandas.read_sql cannot"""
for col, dtype in df.dtypes.items():
if dtype.type == np.object_ and col in query_object.metric_names:
- # soft-convert a metric column to numeric
- # will stay as strings if conversion fails
- df[col] = df[col].infer_objects()
+ # soft-convert a metric column to numeric only if all
+ # non-null values look numeric (e.g. ClickHouse returns
+ # SUM() results as strings). Leaves truly non-numeric
+ # columns unchanged.
+ converted = pd.to_numeric(df[col], errors="coerce")
+ if converted.notna().eq(df[col].notna()).all():
+ df[col] = converted
def is_datetime_series(series: Any) -> bool:
diff --git a/tests/unit_tests/common/test_dataframe_utils.py b/tests/unit_tests/common/test_dataframe_utils.py
index 01fa4224c3c..51d17f401ed 100644
--- a/tests/unit_tests/common/test_dataframe_utils.py
+++ b/tests/unit_tests/common/test_dataframe_utils.py
@@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
import datetime
+from unittest.mock import MagicMock
import pandas as pd
@@ -48,3 +49,27 @@ def test_is_datetime_series():
datetime.datetime(2018, 1, 1), datetime.datetime(2018, 2, 1)
).to_series()
)
+
+
+def test_df_metrics_to_num_converts_string_numerics():
+ """Test that string-encoded numeric columns (e.g. from ClickHouse) are converted."""
+ query_object = MagicMock()
+ query_object.metric_names = ["sum_col", "mixed_col", "text_col"]
+ df = pd.DataFrame(
+ {
+ "sum_col": pd.Series(["100", "200", "300"], dtype=object),
+ "mixed_col": pd.Series(["1", "not_a_number", "3"], dtype=object),
+ "text_col": pd.Series(["foo", "bar", "baz"], dtype=object),
+ "dim_col": pd.Series(["a", "b", "c"], dtype=object),
+ }
+ )
+ dataframe_utils.df_metrics_to_num(df, query_object)
+ # sum_col: all numeric strings -> should be converted to numeric
+ assert pd.api.types.is_numeric_dtype(df["sum_col"]), "sum_col should be numeric"
+ assert df["sum_col"].tolist() == [100.0, 200.0, 300.0]
+ # mixed_col: has non-numeric value -> should NOT be converted
+ assert df["mixed_col"].dtype == object, "mixed_col should remain object"
+ # text_col: all non-numeric -> should NOT be converted
+ assert df["text_col"].dtype == object, "text_col should remain object"
+ # dim_col: not in metric_names -> should NOT be touched
+ assert df["dim_col"].dtype == object, "dim_col should not be touched"