Skip to content

Commit 0116a4b

Browse files
committed
WIP: getting there
1 parent 4c079b7 commit 0116a4b

File tree

2 files changed

+37
-16
lines changed

2 files changed

+37
-16
lines changed

src/pandas_openscm/unit_conversion.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from pandas_openscm.exceptions import MissingOptionalDependencyError
1313
from pandas_openscm.index_manipulation import set_index_levels_func
14-
from pandas_openscm.indexing import multi_index_match
14+
from pandas_openscm.indexing import multi_index_lookup, multi_index_match
1515

1616
if TYPE_CHECKING:
1717
import pint
@@ -50,35 +50,51 @@ def convert_unit(
5050
).T
5151

5252
elif isinstance(desired_unit, pd.Series):
53+
# Don't do this,
54+
# just split out a function which takes in a Series of target_units
55+
# (and do direct passthrough if the user supplies a Series)
5356
raise NotImplementedError
5457
# Assume that desired_unit is already the target units
5558
unit_map = pd.DataFrame([*desired_unit.align(df_units_s)]).T
5659

5760
else:
5861
raise NotImplementedError(type(desired_unit))
5962

60-
if (unit_map["df_unit"] == unit_map["target_unit"]).all():
61-
# Already in matching units
63+
unit_map_no_change = unit_map["df_unit"] == unit_map["target_unit"]
64+
if unit_map_no_change.all():
65+
# Already all in desired unit
6266
return df
6367

64-
df_converted = df.reset_index(unit_level, drop=True)
65-
for (df_unit, target_unit), conversion_df in unit_map.groupby(
68+
df_no_unit = df.reset_index(unit_level, drop=True)
69+
70+
for (df_unit, target_unit), conversion_df in unit_map[~unit_map_no_change].groupby(
6671
["df_unit", "target_unit"]
6772
):
68-
to_alter_loc = multi_index_match(df_converted.index, conversion_df.index) # type: ignore
69-
df_converted.loc[to_alter_loc, :] = (
70-
ur.Quantity(df_converted.loc[to_alter_loc, :].values, df_unit)
73+
to_alter_loc = multi_index_match(df_no_unit.index, conversion_df.index) # type: ignore
74+
df_no_unit.loc[to_alter_loc, :] = (
75+
ur.Quantity(df_no_unit.loc[to_alter_loc, :].values, df_unit)
7176
.to(target_unit)
7277
.m
7378
)
7479

75-
# All conversions done so can simply assign the unit column.
76-
unit_map_reordered = unit_map.reorder_levels(df_converted.index.names)
77-
res = set_index_levels_func(
78-
df_converted,
79-
# use `.loc` to ensure that the values line up with the converted result
80-
{unit_level: unit_map_reordered["target_unit"].loc[df_converted.index]},
81-
).reorder_levels(df.index.names)
80+
missing_from_unit_map = df_no_unit.index.difference(unit_map.index)
81+
if not missing_from_unit_map.empty:
82+
missing_from_unit_map_df = (
83+
multi_index_lookup(df, missing_from_unit_map)
84+
.index.to_frame()[[unit_level]]
85+
.rename({unit_level: "df_unit"}, axis="columns")
86+
)
87+
missing_from_unit_map_df["target_unit"] = missing_from_unit_map_df["df_unit"]
88+
89+
unit_map = pd.concat([unit_map, missing_from_unit_map_df])
90+
91+
new_units = (unit_map.reorder_levels(df_no_unit.index.names).loc[df_no_unit.index])[
92+
"target_unit"
93+
]
94+
95+
res = set_index_levels_func(df_no_unit, {unit_level: new_units}).reorder_levels(
96+
df.index.names
97+
)
8298

8399
return res
84100

tests/integration/test_unit_conversion.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def test_convert_unit_mapping():
8787
# Don't convert W / m^2
8888
res = convert_unit(start, {"Mt CO2/yr": "Gt C/yr", "ZJ": "J"})
8989

90-
np.testing.assert_equal(
90+
np.testing.assert_allclose(
9191
res.loc[res.index.get_level_values("variable") == "co2_emissions", :].values,
9292
12.0
9393
/ 44_000.0
@@ -107,6 +107,11 @@ def test_convert_unit_mapping():
107107
)
108108

109109

110+
def test_convert_series():
111+
# Check that conversion works if user supplies a Series of target units
112+
raise NotImplementedError
113+
114+
110115
def test_convert_unit_like():
111116
start = create_test_df(
112117
variables=[(f"variable_{i}", "Mt") for i in range(5)],

0 commit comments

Comments
 (0)