From 586f06739b443291ba39ae2475a7c418153685b3 Mon Sep 17 00:00:00 2001 From: rwijtvliet Date: Fri, 16 Aug 2024 16:55:10 +0200 Subject: [PATCH] test_wavg2 not yet working --- tests/tools/{test_wavg.py => test_wavg1.py} | 0 tests/tools/test_wavg2.py | 721 +++++--------------- 2 files changed, 178 insertions(+), 543 deletions(-) rename tests/tools/{test_wavg.py => test_wavg1.py} (100%) diff --git a/tests/tools/test_wavg.py b/tests/tools/test_wavg1.py similarity index 100% rename from tests/tools/test_wavg.py rename to tests/tools/test_wavg1.py diff --git a/tests/tools/test_wavg2.py b/tests/tools/test_wavg2.py index 148a64b..c4aa81c 100644 --- a/tests/tools/test_wavg2.py +++ b/tests/tools/test_wavg2.py @@ -14,10 +14,10 @@ @dataclasses.dataclass class Testcase: - values: np.ndarray + values: np.ndarray # 1d or 2d weights: None | np.ndarray # 1d or 2d axis: int - expected: Exception | float | np.ndarray + expected: Exception | float | np.ndarray # 1d TESTCASES = { # values: axis: weights : (expected, id) @@ -52,10 +52,6 @@ class Testcase: }, # 2d values, so 1d result ((100, 100), (200, -200), (300, 300), (-150, -150),): { - # ( - # (100.0, 200, 300, -150), - # (100.0, -200, 300, -150), - # ): { 0: { # 0d weights None: ((112.5, 12.5), "2dvalues_noneweights_ax0"), @@ -65,12 +61,10 @@ class Testcase: (10, 10, 10, 20, 9): (ValueError, "2dvalues_1dweights_moreweights_ax0"), # 2d weights ((10, 10), (10, 10), (10, 30), (20, 0),): ( - # ((10.0, 10, 10, 20), (10.0, 10, 30, 0)): ( (60, 160), "2dvalues_2dweights_ax0", ), ((10, 10), (10, 10), (10, 30),): ( - # ((10.0, 10, 10), (10.0, 10, 30)): ( (200, 160), "2dvalues_2dweights_fewerweights_ax0_A", ), @@ -79,7 +73,6 @@ class Testcase: "2dvalues_2dweights_fewerweights_ax0_B", ), ((10, 10), (10, 10), (10, 30), (20, 0), (30, 40),): ( - # ((10.0, 10, 10, 20, 30), (10.0, 10, 30, 0, 40)): ( ValueError, "2dvalues_2dweights_moreweights_ax0_A", ), @@ -97,32 +90,55 @@ class Testcase: (10, 10, 30): (ValueError, "2dvalues_1dweights_moreweights_ax1"), # 2d weights ((10, 10), (10, 10), (10, 30), (20, 0),): ( - # ((10.0, 10, 10, 20), (10.0, 10, 30, 0)): ( (100, 0, 300, -150), "2dvalues_2dweights_ax1", ), ((10, 10), (10, 10), (10, 30),): ( - # ((10.0, 10, 10), (10.0, 10, 30)): ( (100, 0, 300), "2dvalues_2dweights_fewerweights_ax1_A", ), ((10,), (10,), (10,), (20,),): ( - # ((10.0, 10, 10, 20),): ( (100.0, 200, 300, -150), "2dvalues_2dweights_fewerweights_ax1_B", ), ((10, 10), (10, 10), (10, 30), (20, 0), (30, 40),): ( - # ((10.0, 10, 10, 20, 30), (10.0, 10, 30, 0, 40)): ( ValueError, "2dvalues_2dweights_moreweights_ax1_A", ), ((10, 10, 10), (10, 10, 20), (10, 30, 30), (20, 0, 40),): ( - # ((10.0, 10, 10, 20), (10.0, 10, 30, 0), (10, 20, 30, 40)): ( ValueError, "2dvalues_2dweights_moreweights_ax1_B", ), }, }, + ((100, 100, 100), (200, 100, 100), (150, 100, 200), (100, 100, 250),): { + 0: { + (0, 0, 0, 0): ((np.nan, 100, np.nan), "2dvalues_1dweights_allzero_ax0"), + (-10, 10, 0, 0): ((np.nan, 100, 100), "2dvalues_1dweights_sumzero_ax0"), + ( + (10, 0, -10), + (0, 0, 0), + (0, 0, 0), + (-10, 0, 10), + ): ((100, 100, np.nan), "2dvalues_2dweights_zeros_ax0"), + }, + 1: { + (0, 0, 0): ( + (100, np.nan, np.nan, np.nan), + "2dvalues_1dweights_allzero_ax1", + ), + (10, -10, 0): ( + (100, np.nan, np.nan, 100), + "2dvalues_1dweights_sumzero_ax1", + ), + ( + (10, 0, -10), + (0, 0, 0), + (0, 0, 0), + (-10, 0, 10), + ): ((100, np.nan, np.nan, np.nan), "2dvalues_2dweights_zeros_ax1"), + }, + }, ( (100, 100, 99), (200, -200, -99), @@ -130,15 +146,9 @@ class Testcase: (-150, -150, -99), (99, 99, 99), ): { - # ( - # (100.0, 200, 300, -150, 99), - # (100.0, -200, 300, -150, 99), - # (99.0, -99, 99, -99, 99), - # ): { 0: { # 2d weights ((10, 10), (10, 10), (10, 30), (20, 0),): ( - # ((10.0, 10, 10, 20), (10.0, 10, 30, 0)): ( (60, 160), "2dvalues_2dweights_fewerweights_ax0_C", ), @@ -151,7 +161,6 @@ class Testcase: ), # 2d weights ((10, 10), (10, 10), (10, 30), (20, 0),): ( - # ((10.0, 10, 10, 20), (10.0, 10, 30, 0)): ( (100, 0, 300, -150), "2dvalues_2dweights_fewerweights_ax1_C", ), @@ -252,6 +261,7 @@ def axis(testcase) -> int: ], ) def rowindex(request) -> Sequence: + # Index. Always 5 values. return request.param @@ -301,25 +311,71 @@ def values2d_index_that_remains(values2d_colindex, values2d_rowindex, axis) -> S pytest.param(False, id="valueswithoutunits"), ], ) -def values_has_units(request) -> bool: +def values1d_has_units(request) -> bool: + return request.param + + +@pytest.fixture( + scope="session", + params=[ + "valuesnounits", + "valuesuniformunits", + "valuescompatibleunits", + "valuesincompatibleunits", + ], +) +def values2d_units(request) -> str: return request.param +@pytest.fixture(scope="session") +def values2d_unithelper(values2d_units): + if values2d_units in ["valuesnounits", "valuesuniformunits"]: + return None + + first = "ctEur/kWh" if values2d_units == "valuescompatibleunits" else "MW" + + def gen(): + yield first + while True: + yield "Eur/MWh" + + return gen + + +@pytest.fixture(scope="session") +def values2d_dtypes(values2d_unithelper, values2d_colindex) -> type | str | dict: + if values2d_units == "valuesnounits": + return float + elif values2d_units == "valuesunitformunits": + return "pint[Eur/MWh]" + return { + c: f"pint[{unit}]]" for c, unit in zip(values2d_colindex, values2d_unithelper) + } + + # CREATE VALUES @pytest.fixture(scope="session") -def values1d(values1d_numbers, values_has_units, values1d_rowindex) -> pd.Series: +def values1d(values1d_numbers, values1d_has_units, values1d_rowindex) -> pd.Series: s = pd.Series(values1d_numbers, values1d_rowindex) - return s.astype("pint[Eur/MWh]") if values_has_units else s + return s.astype("pint[Eur/MWh]") if values1d_has_units else s @pytest.fixture(scope="session") def values2d( - values2d_numbers, values_has_units, values2d_rowindex, values2d_colindex + values2d_numbers, + values2d_units, + values2d_dtypes, + values2d_rowindex, + values2d_colindex, ) -> pd.DataFrame: df = pd.DataFrame(values2d_numbers, values2d_rowindex, values2d_colindex) - return df.astype("pint[Eur/MWh]") if values_has_units else df + if values2d_units == "valuescompatibleunits": + firstcol = df.columns[0] + df[firstcol] /= 10 + return df.astype(values2d_dtypes) # PARAMETRIZATION: TYPE OF WEIGHTS @@ -413,7 +469,7 @@ def weights1d( @pytest.fixture(scope="session") def weights2d_rowindex(weights2d_numbers, weights2d_as, rowindex) -> Sequence | None: - # TODO: Can be remove the weights2d_as dependency? + # TODO: Can we remove the weights2d_as dependency? if weights2d_as not in [dict, pd.DataFrame]: return None return rowindex[: weights2d_numbers.shape[0]] @@ -421,6 +477,7 @@ def weights2d_rowindex(weights2d_numbers, weights2d_as, rowindex) -> Sequence | @pytest.fixture(scope="session") def weights2d_colindex(weights2d_numbers, weights2d_as, colindex) -> Sequence | None: + # TODO: Can we remove the weights2d_as dependency? if weights2d_as not in [dict, pd.DataFrame]: return None return colindex[: weights2d_numbers.shape[1]] @@ -465,18 +522,20 @@ def is_exception(x: Any) -> bool: @pytest.fixture(scope="session") def expected_for_values1d_and_weights0d( - expected_numbers, values1d, weights0d, values_has_units + expected_numbers, values1d, weights0d, values1d_has_units ) -> float | pf.Q_ | type: # TODO: Check if we can remove dependency on values1d and weights0d if is_exception(expected_numbers): return expected_numbers - return pf.Q_(expected_numbers, "Eur/MWh") if values_has_units else expected_numbers + return ( + pf.Q_(expected_numbers, "Eur/MWh") if values1d_has_units else expected_numbers + ) @pytest.fixture(scope="session") def expected_for_values1d_and_weights1d( - expected_numbers, values1d, weights1d, values_has_units + expected_numbers, values1d, weights1d, values1d_has_units ) -> float | pf.Q_ | type: if is_exception(expected_numbers): return expected_numbers @@ -484,7 +543,7 @@ def expected_for_values1d_and_weights1d( if isinstance(weights1d, list | tuple) and len(weights1d) != len(values1d.index): return ValueError elif isinstance(weights1d, dict) and any( - w not in values1d.index for w in weights1d + w not in values1d.index for w in weights1d.keys() ): return ValueError elif isinstance(weights1d, pd.Series) and any( @@ -492,21 +551,38 @@ def expected_for_values1d_and_weights1d( ): return ValueError - return pf.Q_(expected_numbers, "Eur/MWh") if values_has_units else expected_numbers + return ( + pf.Q_(expected_numbers, "Eur/MWh") if values1d_has_units else expected_numbers + ) @pytest.fixture(scope="session") def expected_for_values2d_and_weights0d( expected_numbers, - weights0d, values2d_index_that_remains, - values_has_units, + values2d_units, + values2d_unithelper, + axis, ) -> pd.Series | type: if is_exception(expected_numbers): return expected_numbers + if values2d_units == "valuesincompatibleunits" and axis == 1: + return ValueError # can't calc wavg across columns with incompatible units + s = pd.Series(expected_numbers, values2d_index_that_remains) - return s.astype("pint[Eur/MWh]") if values_has_units else s + if values2d_units == "valuesnounits": + return s + elif values2d_units in ["valuesuniformunits", "valuescompatibleunits"]: + return s.astype("pint[Eur/MWh]") + else: # (values2d_units == "valuesincompatibleunits" and axis == 0) + # series of quantities + return pd.Series( + { + i: pf.Q_(num, unit) + for (i, num), unit in zip(s.items(), values2d_unithelper()) + } + ) @pytest.fixture(scope="session") @@ -515,7 +591,9 @@ def expected_for_values2d_and_weights1d( weights1d, values2d_index_that_remains, values2d_index_that_collapses, - values_has_units, + values2d_units, + values2d_unithelper, + axis, ) -> pd.Series | type: if is_exception(expected_numbers): return expected_numbers @@ -525,15 +603,29 @@ def expected_for_values2d_and_weights1d( ): return ValueError elif isinstance(weights1d, dict) and any( - w not in values2d_index_that_collapses for w in weights1d + w not in values2d_index_that_collapses for w in weights1d.keys() ): return ValueError elif isinstance(weights1d, pd.Series) and any( w not in values2d_index_that_collapses for w in weights1d.index ): return ValueError + if values2d_units == "valuesincompatibleunits" and axis == 1: + # can't calc wavg across columns if columns have incompatible units + return ValueError + s = pd.Series(expected_numbers, values2d_index_that_remains) - return s.astype("pint[Eur/MWh]") if values_has_units else s + if values2d_units == "valuesnounits": + return s + elif values2d_units in ["valuesuniformunits", "valuescompatibleunits"]: + return s.astype("pint[Eur/MWh]") + else: # (values2d_units == "valuesincompatibleunits" and axis == 0) + return pd.Series( + { + i: pf.Q_(num, unit) + for (i, num), unit in zip(s.items(), values2d_unithelper()) + } + ) @pytest.fixture(scope="session") @@ -542,7 +634,9 @@ def expected_for_values2d_and_weights2d( weights2d, values2d_rowindex, values2d_colindex, - values_has_units, + values2d_units, + values2d_unithelper, + axis, values2d_index_that_remains, ) -> pd.Series | type: if is_exception(expected_numbers): @@ -562,8 +656,22 @@ def expected_for_values2d_and_weights2d( or any(rowi not in values2d_rowindex for rowi in weights2d.index) ): return ValueError + if values2d_units == "valuesincompatibleunits" and axis == 1: + # can't calc wavg across columns if columns have incompatible units + return ValueError + s = pd.Series(expected_numbers, values2d_index_that_remains) - return s.astype("pint[Eur/MWh]") if values_has_units else s + if values2d_units == "valuesnounits": + return s + elif values2d_units in ["valuesuniformunits", "valuescompatibleunits"]: + return s.astype("pint[Eur/MWh]") + else: # (values2d_units == "valuesincompatibleunits" and axis == 0) + return pd.Series( + { + i: pf.Q_(num, unit) + for (i, num), unit in zip(s.items(), values2d_unithelper()) + } + ) # DO THE TESTS. FINALLY. @@ -599,6 +707,36 @@ def test_wavg_values1d_weights1d( pf.testing.assert_value_equal(result, expected) +@pytest.mark.parametrize( + "val,wei,exp", + [ + pytest.param( + "values1d", + "weights0d", + "expected_for_values1d_and_weights0d", + ), + pytest.param( + "values1d", + "weights1d", + "expected_for_values1d_and_weights1d", + ), + ], +) +def test_wavg_values1d(request, val, wei, exp): + s = val + weights = request.getfixturevalue(wei) + expected = request.getfixturevalue(exp) + testfn = lambda: tools.wavg.series(s, weights) # noqa + + if is_exception(expected): + with pytest.raises(expected): + testfn() + return + + result = testfn() + pf.testing.assert_value_equal(result, expected) + + def test_wavg_values2d_weights0d( values2d, weights0d, axis, expected_for_values2d_and_weights0d ): @@ -644,36 +782,6 @@ def test_wavg_values2d_weights2d( pf.testing.assert_series_equal(result, expected, check_names=False, check_like=True) -@pytest.mark.parametrize( - "val,wei,exp", - [ - pytest.param( - "values1d", - "weights0d", - "expected_for_values1d_and_weights0d", - ), - pytest.param( - "values1d", - "weights1d", - "expected_for_values1d_and_weights1d", - ), - ], -) -def test_wavg_values1d(request, val, wei, exp): - s = val - weights = request.getfixturevalue(wei) - expected = request.getfixturevalue(exp) - testfn = lambda: tools.wavg.series(s, weights) # noqa - - if is_exception(expected): - with pytest.raises(expected): - testfn() - return - - result = testfn() - pf.testing.assert_value_equal(result, expected) - - @pytest.mark.parametrize( "val,wei,exp", [ @@ -707,476 +815,3 @@ def test_wavg_values2d(request, val, wei, exp, axis): result = testfn() pf.testing.assert_series_equal(result, expected) - - -# # Numbers in general. -# -# -# @pytest.fixture(scope="session", params=[{"v": [100.0, 200, 300, -150], "e": 112.5}]) -# def numbers_0d(request) -> Dict[str, List[float] | float]: -# return request.param -# -# -# @pytest.fixture( -# scope="session", -# params=[{"v": [100.0, 200, 300, -150], "w": [10.0, 0, 10, 20], "e": 25.0}], -# ) -# def numbers_1d(request) -> Dict[str, List[float] | float]: -# return request.param -# -# -# -# # Values. -# -# -# -# @pytest.fixture(scope="session") -# def values(index: Iterable, numbers_1d: Dict, values_has_units: bool) -> Iterable: -# return create_values(index, numbers_1d["v"], values_has_units) -# -# -# def create_values(index: Iterable, numbers: Dict, values_has_units: bool): -# s = pd.Series(numbers, index) -# if values_has_units: -# return s.astype("pint[Eur/MWh]") -# return s -# -# -# # Weigths. -# -# -# -# -# @pytest.fixture(scope="session", params=["none", "list", "dict", "series", "df"]) -# def weightsas(request) -> str: -# return request.param -# -# -# @pytest.fixture -# def weights_as_list(numbers_1d, weights_has_units) -> List: -# if weights_has_units: -# return [pf.Q_(w, "MWh") for w in numbers_1d["w"]] -# return numbers_1d["w"] -# -# -# @pytest.fixture -# def weights_as_series(numbers_1d, weights_has_units, index) -> pd.Series: -# s = pd.Series({i: w for w, i in zip(numbers_1d["w"][::-1], index[::-1])}) -# if weights_has_units: -# return s.astype("pint[MWh]") -# return s -# -# -# @pytest.fixture -# def weights_as_dict(numbers_1d, weights_has_units, index) -> Dict: -# d = {i: w for w, i in zip(numbers_1d["w"][::-1], index[::-1])} -# if weights_has_units: -# return {i: pf.Q_(w, "MWh") for i, w in d.items()} -# return d -# -# -# @pytest.fixture -# def weights(numbers_1d, weights_has_units, index, weightsas): -# if weightsas == "none": -# return None -# @pytest.fixture(scope="session") -# def testcase_values(testcase: testcase, values_has_units: bool, index: Iterable) -> pd.DataFrame: -# s = pd.Series(pd.testcase.values, index) -# if values_has_units: -# return s.astype("pint[Eur/MWh]") -# return s -# -# if weightsas == "list": -# return weights_as_list(numbers_1d, weights_has_units) -# if weightsas == "series": -# return weights_as_series(numbers_1d, weights_has_units, index) -# -# -# @pytest.fixture -# def weights_as_df(numbers_2d: dict, index: Iterable, units: bool = False): -# """Get weights to test wavg with, if weightsas == 'dataframe'.""" -# weights = pd.DataFrame(weightsnumbers, index) -# if units: -# weights = pd.DataFrame( -# {c: s.astype("pint[Eur/MWh]") for c, s in weights.items()} -# ) -# return weights -# -# -# @pytest.fixture -# def weights(weights_as_dict, weights_as_list, weights_as_series): -# return [weights_as_dict] + [weights_as_list] + [weights_as_series] -# -# -# # Expected. -# -# -# @pytest.fixture(scope="session") -# def expected(expectednumber: float, values_has_units: bool) -> float | pf.Q_: -# if values_has_units: -# return pf.Q_(expectednumber, "Eur/MWh") -# return expectednumber -# - - -def get_weights( - weights: Iterable[float], - weightsas: str, - index: Iterable = None, - units: bool = False, -): - """Get weights to test wavg with, if weightsas == 'none', 'list', 'dict', or 'series'.""" - # No weights. - if weightsas == "none": - if units: - pytest.skip("Cannot test weights == None with units.") - return None - # Weights as list, no index needed. - if weightsas == "list": - if units: - weights = [pf.Q_(w, "MWh") for w in weights] - return weights - # Weights include index value; make index if needed. - if index is None: - index = range(len(weights)) - weights = {i: w for w, i in zip(weights[::-1], index[::-1])} - if weightsas == "dict": - if units: - weights = {i: pf.Q_(w, "MWh") for i, w in weights.items()} - return weights - if weightsas == "series": - weights = pd.Series(weights) - if units: - weights = weights.astype("pint[MWh]") - return weights - - -def get_weights_df(weights: dict, index: Iterable, units: bool = False): - """Get weights to test wavg with, if weightsas == 'dataframe'.""" - weights = pd.DataFrame(weights, index) - if units: - weights = pd.DataFrame( - {c: s.astype("pint[Eur/MWh]") for c, s in weights.items()} - ) - return weights - - -def get_index(number: int, indextype: str) -> Iterable: - if indextype == "int": - return range(number) - return pd.date_range("2020", freq="D", periods=number) - - -def do_test_series( - values: pd.Series | pd.DataFrame, weights: Any, expected: Any, **kwargs -): - if isinstance(expected, type) and issubclass(expected, Exception): - with pytest.raises(expected): - tools.wavg.series(values, weights) - return - pf.testing.assert_value_equal(tools.wavg.series(values, weights), expected) - - -def do_test_dataframe(values: pd.DataFrame, weights: Any, expected: Any, **kwargs): - if isinstance(expected, type) and issubclass(expected, Exception): - with pytest.raises(expected): - tools.wavg.dataframe(values, weights, **kwargs) - return - result = tools.wavg.dataframe(values, weights, **kwargs) - pf.testing.assert_series_equal(result, expected) - - -# @pytest.mark.parametrize("weightsas", ["none", "list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# def test_wavg_series(weightsas: str, units: str, indextype: str): -# """Test if weighted average of a series is correctly calculated.""" -# # Starting values. -# i = get_index(4, indextype) -# values = pd.Series([100.0, 200, 300, -150], i) -# weights = get_weights([10.0, 0, 10, 20], weightsas, i, "wei" in units) -# if weightsas == "none": -# expected = 112.5 -# else: -# expected = 25.0 -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# expected = pf.Q_(expected, "Eur/MWh") -# # Test. -# do_test_series(values, weights, expected) - - -# @pytest.mark.parametrize("weightsas", ["list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# def test_wavg_series_surplusvalues(weightsas: str, units: str, indextype: str): -# """Test if weighted average of a series is correctly calculated if we have more -# values and than weights.""" -# # Starting values. -# i = get_index(5, indextype) -# values = pd.Series([100.0, 200, 300, -150, 100], i) -# weights = get_weights([10.0, 0, 10, 20], weightsas, i[:4], "wei" in units) -# expected = 25.0 -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# expected = pf.Q_(expected, "Eur/MWh") -# if weightsas == "list": -# expected = ValueError -# # Test. -# do_test_series(values, weights, expected) - - -# @pytest.mark.parametrize("weightsas", ["list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# def test_wavg_series_surplusweights(weightsas: str, units: str, indextype: str): -# """Test if error is correctly thrown if we have more weights than values.""" -# # Starting values. -# i = get_index(5, indextype) -# values = pd.Series([100.0, 200, 300, -150], i[:4]) -# weights = get_weights([10.0, 0, 10, 20, 10], weightsas, i, "wei" in units) -# expected = ValueError -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# # Test. -# do_test_series(values, weights, expected) - - -# @pytest.mark.parametrize("weightsas", ["list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# @pytest.mark.parametrize("zerovalues", ["allzero", "sumzero"]) -# def test_wavg_series_0weights( -# weightsas: str, units: str, indextype: str, zerovalues: str -# ): -# """Test if weighted average of a series is correctly identified as error, -# when sum of weights is 0 but not all values are equal.""" -# # Starting values. -# i = get_index(4, indextype) -# values = pd.Series([100.0, 200, 300, -150], i) -# weightvalues = [0.0, 0, 0, 0] if zerovalues == "allzero" else [-10.0, 10, 0, 0] -# weights = get_weights(weightvalues, weightsas, i, "wei" in units) -# expected = np.nan -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# # Test. -# do_test_series(values, weights, expected) - - -# @pytest.mark.parametrize("weightsas", ["list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# @pytest.mark.parametrize("zerovalues", ["allzero", "sumzero"]) -# def test_wavg_onevalseries_0weights( -# weightsas: str, units: str, indextype: str, zerovalues: str -# ): -# """Test if weighted average of a series is correctly calculated, -# when sum of weights is 0 and all values are equal.""" -# # Starting values. -# i = get_index(4, indextype) -# values = pd.Series([100.0, 100, 100, 100], i) -# weightvalues = [0.0, 0, 0, 0] if zerovalues == "allzero" else [-10.0, 10, 0, 0] -# weights = get_weights(weightvalues, weightsas, i, "wei" in units) -# expected = 100.0 -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# expected = pf.Q_(expected, "Eur/MWh") -# if zerovalues == "allzero": -# expected = np.nan -# # Test. -# do_test_series(values, weights, expected) - -# -# # @pytest.mark.parametrize("weightsas", ["list", "dict", "series"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# def test_wavg_naseries_0weights(weightsas: str, units: str, indextype: str): -# """Test if weighted average of a series is correctly calculated, when some weights -# are 0 but they have na-values.""" -# # Starting values. -# i = get_index(4, indextype) -# values = pd.Series([100.0, 200, np.nan, -150], i) -# weights = get_weights([10.0, 0, 0, 0], weightsas, i, "wei" in units) -# expected = 100.0 -# # Add units. -# if "val" in units: -# values = values.astype("pint[Eur/MWh]") -# expected = pf.Q_(expected, "Eur/MWh") -# # Test. -# do_test_series(values, weights, expected) - - -# @pytest.mark.parametrize("weightsas", ["list", "dict", "series", "dataframe"]) -# @pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -# @pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -# @pytest.mark.parametrize("axis", [0, 1]) -# def test_wavg_dataframe_surplusweights( -# weightsas: str, axis: int, units: str, indextype: str -# ): -# """Test if error is correctly thrown if we have more weights than values.""" -# # Starting values. -# i = get_index(5, indextype) -# series_a = pd.Series([100.0, 200, 300, -150], i[:4]) -# series_b = pd.Series([100.0, -200, 300, -150], i[:4]) -# values = pd.DataFrame({"a": series_a, "b": series_b}) - -# if weightsas != "dataframe": -# if axis == 0: -# weights = get_weights([10.0, 10, 10, 20, 9], weightsas, i, "wei" in units) -# else: -# weights = get_weights( -# [10.0, 30, 9], weightsas, ["a", "b", "c"], "wei" in units -# ) -# else: -# weights = get_weights_df( -# {"a": [10.0, 10, 10, 20, 9], "b": [10.0, 10, 30, 0, 9]}, i, "wei" in units -# ) -# if "val" in units: -# values = pd.DataFrame({c: s.astype("pint[Eur/MWh]") for c, s in values.items()}) -# # Test. -# do_test_dataframe(values, weights, ValueError, axis=axis) - - -@pytest.mark.parametrize("weightsas", ["none", "list", "series", "dataframe"]) -@pytest.mark.parametrize("axis", [0, 1]) -@pytest.mark.parametrize("compatible", ["compatible", "incompatible"]) -@pytest.mark.parametrize("units", ["val", "val&wei"]) -@pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -def test_wavg_dataframe_distinctunits( - weightsas: str, axis: int, compatible: str, units: str, indextype: str -): - """Test if weighted average of a dataframe is correctly calculated if it has a mix - of units.""" - # Starting values. - i = get_index(4, indextype) - series_a = pd.Series([100.0, 200, 300, -150], i).astype("pint[Eur/MWh]") - if compatible == "compatible": - series_b = pd.Series([10.0, -20, 30, -15], i).astype("pint[ctEur/kWh]") - else: - series_b = pd.Series([100.0, -200, 300, -150], i).astype("pint[MW]") - values = pd.DataFrame({"a": series_a, "b": series_b}) - - def exp_res(val_a, val_b): - if compatible == "compatible": - return pd.Series({"a": val_a, "b": val_b}, dtype="pint[Eur/MWh]") - return pd.Series({"a": pf.Q_(val_a, "Eur/MWh"), "b": pf.Q_(val_b, "MW")}) - - if weightsas != "dataframe": - if axis == 0: - weights = get_weights([10.0, 10, 10, 20], weightsas, i, "wei" in units) - if weightsas == "none": - expected = exp_res(112.5, 12.5) - else: - expected = exp_res(60.0, -20.0) - else: - weights = get_weights([10.0, 30], weightsas, ["a", "b"], "wei" in units) - if weightsas == "none": - expected = pd.Series([100.0, 0, 300, -150], i).astype("pint[Eur/MWh]") - else: - expected = pd.Series([100.0, -100, 300, -150], i).astype( - "pint[Eur/MWh]" - ) - else: - weights = get_weights_df( - {"a": [10.0, 10, 10, 20], "b": [10.0, 10, 30, 0]}, i, "wei" in units - ) - if axis == 0: - expected = exp_res(60.0, 160.0) - else: - expected = pd.Series([100.0, 0, 300, -150], i).astype("pint[Eur/MWh]") - - # Test. - if axis == 1 and compatible != "compatible": # error cases - expected = Exception - do_test_dataframe(values, weights, expected, axis=axis) - - -@pytest.mark.parametrize("weightsas", ["list", "series", "dataframe"]) -@pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -@pytest.mark.parametrize("axis", [0, 1]) -def test_wavg_dataframe_na(weightsas: str, axis: int, indextype: str): - """Test if weighted average of a dataframe is correctly identified as error, - when all weights are 0 but not all values are equal.""" - # Starting values. - i = get_index(4, indextype) - values = pd.DataFrame({"a": [130, 200, 200, -160], "b": [100, -200, 300, -150]}, i) - if axis == 0: - weights = [0, 0, 0, 0] - expected = pd.Series({"a": np.nan, "b": np.nan}) - else: - weights = [0, 0] - expected = pd.Series([np.nan, np.nan, np.nan, np.nan], i) - - if weightsas == "series": - if axis == 0: - weights = pd.Series(weights, [i[j] for j in [3, 2, 1, 0]]) - else: - weights = pd.Series(weights, ["a", "b"]) - elif weightsas == "dataframe": - weights = pd.DataFrame({"a": [0, 0, 0, 0], "b": [0, 0, 0, 0]}, i) - # Test. - do_test_dataframe(values, weights, expected, axis=axis) - - -@pytest.mark.parametrize("weightsas", ["list", "series", "dataframe"]) -@pytest.mark.parametrize("axis", [0, 1]) -@pytest.mark.parametrize("zerovalues", ["allzero", "sumzero"]) -@pytest.mark.parametrize("indextype", ["int", "DatetimeIndex"]) -@pytest.mark.parametrize("units", ["", "val", "wei", "val&wei"]) -def test_wavg_dataframe_0weights( - weightsas: str, axis: int, units: str, zerovalues: str, indextype: str -): - """Test if weighted average of a dataframe is correctly identified as error, - when sum of weights is 0. Some averages are calculated from identical values and should - result in that value.""" - # Starting values. - i = get_index(4, indextype) - values = pd.DataFrame( - { - "a": [100.0, 200, 150, 100], - "b": [100.0, 100, 100, 100], - "c": [100.0, 100, 200, 250], - }, - i, - ) - if weightsas != "dataframe": - if axis == 0: - if zerovalues == "allzero": - weightvalues = [0.0, 0, 0, 0] - expectedvalues = [np.nan, 100.0, np.NaN] - else: - weightvalues = [-10.0, 10, 0, 0] - expectedvalues = [np.nan, 100.0, 100] - weights = get_weights(weightvalues, weightsas, i, "wei" in units) - expected = pd.Series(expectedvalues, list("abc")) - else: - if zerovalues == "allzero": - weightvalues = [0.0, 0, 0] - expectedvalues = [100.0, np.nan, np.nan, np.nan] - else: - weightvalues = [-10.0, 10, 0] - expectedvalues = [100.0, np.nan, np.nan, 100.0] - weights = get_weights(weightvalues, weightsas, list("abc"), "wei" in units) - expected = pd.Series(expectedvalues, i) - else: - if zerovalues == "allzero": - pytest.skip("Testing both zero cases together.") - weights = get_weights_df( - {"a": [10.0, 0, 0, -10], "b": [0.0, 0, 0, 0], "c": [-10, 0, 0, 10]}, - i, - "wei" in units, - ) - if axis == 0: - expected = pd.Series([100.0, 100, np.nan], list("abc")) - else: - expected = pd.Series([100.0, np.nan, np.nan, np.nan], i) - if "val" in units: - values = pd.DataFrame({c: s.astype("pint[Eur/MWh]") for c, s in values.items()}) - expected = expected.astype("pint[Eur/MWh]") - # Test. - do_test_dataframe(values, weights, expected, axis=axis)