Repository: IAMconsortium/pyam
Pull request #62 (2018-04-26 13:07:45)

Add rename function


Patch:
diff --git a/pyam/core.py b/pyam/core.py
index b84fe84..eed4e69 100644
--- a/pyam/core.py
+++ b/pyam/core.py
@@ -29,6 +29,7 @@ from pyam.utils import (
     META_IDX,
     IAMC_IDX,
     SORT_IDX,
+    LONG_IDX,
 )
 from pyam.timeseries import fill_series
 
@@ -405,6 +406,27 @@ class IamDataFrame(object):
 
             return df
 
+    def rename(self, mapping, inplace=False):
+        """ Rename and aggregate column entries using groupby.sum()
+
+        Parameters
+        ----------
+        mapping: dict
+            for each column where entries should be renamed, provide current name and target name
+            {<column name>: {<current_name_1>: <target_name_1>, <current_name_2>: <target_name_2>}}
+        inplace: bool, default False
+            if True, do operation inplace and return None
+        """
+        ret = copy.deepcopy(self) if not inplace else self
+        for col in mapping:
+            if not col in ['region', 'variable', 'unit']:
+                raise ValueError('renaming by {} not supported!'.format(col))
+            ret.data.loc[:, col] = self.data.loc[:, col].replace(mapping[col])
+
+        ret.data = ret.data.groupby(LONG_IDX).sum().reset_index()
+        if not inplace:
+            return ret
+
     def filter(self, filters, keep=True, inplace=False):
         """Return a filtered IamDataFrame (i.e., a subset of current data)
 
@@ -636,7 +658,7 @@ class IamDataFrame(object):
 
         # perform aggregations
         if agg == 'sum':
-            df = df.groupby(IAMC_IDX + ['year']).sum().reset_index()
+            df = df.groupby(LONG_IDX).sum().reset_index()
 
         ret.data = (df
                     .reindex(columns=columns_orderd)
diff --git a/pyam/utils.py b/pyam/utils.py
index a66c0b5..bf5b44e 100644
--- a/pyam/utils.py
+++ b/pyam/utils.py
@@ -30,6 +30,7 @@ from pyam.logger import logger
 META_IDX = ['model', 'scenario']
 IAMC_IDX = ['model', 'scenario', 'region', 'variable', 'unit']
 SORT_IDX = ['model', 'scenario', 'variable', 'year', 'region']
+LONG_IDX = IAMC_IDX + ['year']
 
 # dictionary to translate column count to Excel column names
 NUMERIC_TO_STR = dict(zip(range(0, 702),


Test patch:
diff --git a/tests/test_core.py b/tests/test_core.py
index e475cad..4f9246c 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -445,3 +445,25 @@ def test_48b():
     obs = obs[obs.region.isin(['SSD', 'SDN'])].reset_index(drop=True)
 
     pd.testing.assert_frame_equal(obs, exp, check_index_type=False)
+
+def test_rename():
+    df = IamDataFrame(pd.DataFrame([
+        ['model', 'scen', 'SST', 'test_1', 'unit', 1, 5],
+        ['model', 'scen', 'SDN', 'test_2', 'unit', 2, 6],
+        ['model', 'scen', 'SST', 'test_3', 'unit', 3, 7],
+    ], columns=['model', 'scenario', 'region',
+                'variable', 'unit', 2005, 2010],
+    ))
+
+    mapping = {'variable': {'test_1': 'test', 'test_3': 'test'}}
+
+    obs = df.rename(mapping).data.reset_index(drop=True)
+
+    exp = IamDataFrame(pd.DataFrame([
+        ['model', 'scen', 'SST', 'test', 'unit', 4, 12],
+        ['model', 'scen', 'SDN', 'test_2', 'unit', 2, 6],
+    ], columns=['model', 'scenario', 'region',
+                'variable', 'unit', 2005, 2010],
+    )).data.sort_values(by='region').reset_index(drop=True)
+
+    pd.testing.assert_frame_equal(obs, exp, check_index_type=False)