# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. import warnings import pytest from superset.exceptions import InvalidPostProcessingError from superset.utils.core import PostProcessingBoxplotWhiskerType from superset.utils.pandas_postprocessing import boxplot from tests.unit_tests.fixtures.dataframes import names_df from tests.unit_tests.pandas_postprocessing.utils import series_to_list def test_boxplot_tukey(): df = boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.TUKEY, metrics=["cars"], ) columns = {column for column in df.columns} # noqa: C416 assert columns == { "cars__mean", "cars__median", "cars__q1", "cars__q3", "cars__max", "cars__min", "cars__count", "cars__outliers", "region", } assert len(df) == 4 def test_boxplot_mean_median_no_future_warning(): """mean/median must be passed as strings (not np.mean/np.median) to GroupBy.agg, else pandas raises a FutureWarning. Also verify the values match a plain pandas groupby, since the string and callable forms could silently diverge on a future pandas version.""" expected = names_df.groupby("region")["cars"].agg(["mean", "median"]) with warnings.catch_warnings(): warnings.simplefilter("error", FutureWarning) df = boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.TUKEY, metrics=["cars"], ) df = df.set_index("region") assert series_to_list(df["cars__mean"]) == series_to_list(expected["mean"]) assert series_to_list(df["cars__median"]) == series_to_list(expected["median"]) def test_boxplot_min_max(): df = boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.MINMAX, metrics=["cars"], ) columns = {column for column in df.columns} # noqa: C416 assert columns == { "cars__mean", "cars__median", "cars__q1", "cars__q3", "cars__max", "cars__min", "cars__count", "cars__outliers", "region", } assert len(df) == 4 def test_boxplot_percentile(): df = boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.PERCENTILE, metrics=["cars"], percentiles=[1, 99], ) columns = {column for column in df.columns} # noqa: C416 assert columns == { "cars__mean", "cars__median", "cars__q1", "cars__q3", "cars__max", "cars__min", "cars__count", "cars__outliers", "region", } assert len(df) == 4 def test_boxplot_percentile_incorrect_params(): with pytest.raises(InvalidPostProcessingError): boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.PERCENTILE, metrics=["cars"], ) with pytest.raises(InvalidPostProcessingError): boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.PERCENTILE, metrics=["cars"], percentiles=[10], ) with pytest.raises(InvalidPostProcessingError): boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.PERCENTILE, metrics=["cars"], percentiles=[90, 10], ) with pytest.raises(InvalidPostProcessingError): boxplot( df=names_df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.PERCENTILE, metrics=["cars"], percentiles=[10, 90, 10], ) def test_boxplot_type_coercion(): df = names_df df["cars"] = df["cars"].astype(str) df = boxplot( df=df, groupby=["region"], whisker_type=PostProcessingBoxplotWhiskerType.TUKEY, metrics=["cars"], ) columns = {column for column in df.columns} # noqa: C416 assert columns == { "cars__mean", "cars__median", "cars__q1", "cars__q3", "cars__max", "cars__min", "cars__count", "cars__outliers", "region", } assert len(df) == 4