Skip to content

Commit 22e5d4c

Browse files
committed
passing tests
1 parent dae8d46 commit 22e5d4c

File tree

2 files changed

+23
-28
lines changed

2 files changed

+23
-28
lines changed

src/pandas_openscm/index_manipulation.py

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -741,29 +741,22 @@ def set_levels(
741741
ValueError
742742
If the length of the values is not equal to the length of the index
743743
"""
744-
# set the levels specified in levels_to_set to the provided values
745-
#
746-
# We should support both single values e.g. levels_to_set={"variable": "Emissions"}
747-
# and values with the same length as the index itself e.g.
748-
# levels_to_set={"variable": ["a", "b", "c"]}.
749-
# Values of any other length should raise an error (because we don't know what to do
750-
# if the index is say 4 elements long but the user only gives us 3 values)
751-
#
752-
# This should work whether the level to be set exists or not
753-
# TODO: move to pandas-openscm
754-
# TODO: split out method that just works on MultiIndex
755-
756-
new_names = levels_to_set.keys()
757-
new_values = levels_to_set.values()
758-
759744
if not isinstance(ini, pd.MultiIndex):
760-
raise TypeError(ini)
745+
msg = f"Expected MultiIndex, got {type(ini)}"
746+
raise TypeError(msg)
761747

762-
return pd.MultiIndex(
763-
codes=[
764-
*ini.codes, # type: ignore # not sure why check above isn't working
765-
*([[0] * ini.shape[0]] * len(new_values)), # type: ignore # fix when moving to pandas-openscm
766-
],
767-
levels=[*ini.levels, *[pd.Index([value]) for value in new_values]], # type: ignore # fix when moving to pandas-openscm
768-
names=[*ini.names, *new_names], # type: ignore # fix when moving to pandas-openscm
769-
)
748+
df = ini.to_frame(index=False)
749+
750+
for level, value in levels_to_set.items():
751+
if isinstance(value, Collection) and not isinstance(value, str):
752+
if len(value) != len(ini):
753+
msg = (
754+
f"Length of values for level '{level}' does not "
755+
f"match index length: {len(value)} != {len(ini)}"
756+
)
757+
raise ValueError(msg)
758+
df[level] = value
759+
else:
760+
df[level] = [value] * len(ini)
761+
762+
return pd.MultiIndex.from_frame(df)

tests/integration/index_manipulation/test_integration_index_manipulation_set_levels.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@
5151
],
5252
names=["scenario", "variable", "unit", "run_id", "new_variable"],
5353
),
54-
id="set-multiple-levels",
54+
id="set-multiple-values",
5555
),
5656
pytest.param(
5757
pd.MultiIndex.from_tuples(
5858
[
59-
("sa", "va", "kg", 0),
59+
("sa", "va", "kg", 5),
6060
("sb", "vb", "m", 1),
6161
("sa", "va", "kg", 2),
6262
],
@@ -65,7 +65,7 @@
6565
{"variable": ["a", "b", "c"]},
6666
pd.MultiIndex.from_tuples(
6767
[
68-
("sa", "a", "kg", 0),
68+
("sa", "a", "kg", 5),
6969
("sb", "b", "m", 1),
7070
("sa", "c", "kg", 2),
7171
],
@@ -110,6 +110,8 @@ def test_set_levels_raises_value_error():
110110
levels_to_set = {"new_variable": ["a", "b", "c", "d"]}
111111

112112
with pytest.raises(
113-
ValueError, match="Length of values does not match, got 4 but expected 3"
113+
ValueError,
114+
match="Length of values for level 'new_variable' "
115+
"does not match index length: 4 != 3",
114116
):
115117
set_levels(start, levels_to_set=levels_to_set)

0 commit comments

Comments
 (0)