Skip to content

Commit 0b06f3f

Browse files
DiscRates csv support (#818)
* DiscRates: add csv support * changelog
1 parent a8cb0d2 commit 0b06f3f

File tree

3 files changed

+103
-10
lines changed

3 files changed

+103
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Code freeze date: YYYY-MM-DD
1212

1313
### Added
1414

15+
- Read and Write methods to and from csv files for the `DiscRates` class. [#818](ttps://github.com/CLIMADA-project/climada_python/pull/818)
16+
1517
### Changed
1618

1719
- Add `shapes` argument to `geo_im_from_array` to allow flexible turning on/off of plotting coastline in `plot_intensity`. [#805](https://github.com/CLIMADA-project/climada_python/pull/805)

climada/entity/disc_rates/base.py

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ def from_mat(cls, file_name, var_names=None):
259259
return cls(years=years, rates=rates)
260260

261261
def read_mat(self, *args, **kwargs):
262-
"""This function is deprecated, use DiscRates.from_mats instead."""
263-
LOGGER.warning("The use of DiscRates.read_mats is deprecated."
264-
"Use DiscRates.from_mats instead.")
262+
"""This function is deprecated, use ``DiscRates.from_mat`` instead."""
263+
LOGGER.warning(
264+
"The use of DiscRates.read_mat is deprecated."
265+
"Use DiscRates.from_mat instead."
266+
)
265267
self.__dict__ = DiscRates.from_mat(*args, **kwargs).__dict__
266268

267269
@classmethod
@@ -307,8 +309,7 @@ def read_excel(self, *args, **kwargs):
307309
"""This function is deprecated, use DiscRates.from_excel instead."""
308310
LOGGER.warning("The use of DiscRates.read_excel is deprecated."
309311
"Use DiscRates.from_excel instead.")
310-
self.__dict__ = DiscRates.from_mat(*args, **kwargs).__dict__
311-
312+
self.__dict__ = DiscRates.from_excel(*args, **kwargs).__dict__
312313

313314
def write_excel(self, file_name, var_names=None):
314315
"""
@@ -341,3 +342,68 @@ def write_excel(self, file_name, var_names=None):
341342
disc_ws.write(i_yr, 0, disc_yr)
342343
disc_ws.write(i_yr, 1, disc_rt)
343344
disc_wb.close()
345+
346+
@classmethod
347+
def from_csv(
348+
cls, file_name, year_column="year", disc_column="discount_rate", **kwargs
349+
):
350+
"""
351+
Read DiscRate from a csv file following template and store variables.
352+
353+
Parameters
354+
----------
355+
file_name: str
356+
filename including path and extension
357+
year_column: str, optional
358+
name of the column that contains the years,
359+
Default: "year"
360+
disc_column: str, optional
361+
name of the column that contains the discount rates,
362+
Default: "discount_rate"
363+
**kwargs:
364+
any additional arguments, e.g., `sep`, `delimiter`, `head`,
365+
are forwarded to ``pandas.read_csv``
366+
367+
Returns
368+
-------
369+
climada.entity.DiscRates :
370+
The disc rates from the csv file
371+
"""
372+
dfr = pd.read_csv(file_name, **kwargs)
373+
try:
374+
years = dfr[year_column].values.astype(int, copy=False)
375+
rates = dfr[disc_column].values
376+
except KeyError as err:
377+
raise ValueError(
378+
f"missing column in csv file ({year_column} or {disc_column})"
379+
) from err
380+
381+
return cls(years=years, rates=rates)
382+
383+
def write_csv(
384+
self, file_name, year_column="year", disc_column="discount_rate", **kwargs
385+
):
386+
"""
387+
Write DiscRate to a csv file following template and store variables.
388+
389+
Parameters
390+
----------
391+
file_name: str
392+
filename including path and extension
393+
year_column: str, optional
394+
name of the column that contains the years,
395+
Default: "year"
396+
disc_column: str, optional
397+
name of the column that contains the discount rates,
398+
Default: "discount_rate"
399+
**kwargs:
400+
any additional arguments, e.g., `sep`, `delimiter`, `head`,
401+
are forwarded to ``pandas.read_csv``
402+
"""
403+
dfr = pd.DataFrame(
404+
{
405+
year_column: self.years,
406+
disc_column: self.rates,
407+
}
408+
)
409+
dfr.to_csv(file_name, **kwargs)

climada/entity/disc_rates/test/test_base.py

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import unittest
2222
import numpy as np
2323
import copy
24+
from pathlib import Path
25+
from tempfile import TemporaryDirectory
2426

2527
from climada import CONFIG
2628
from climada.entity.disc_rates.base import DiscRates
@@ -216,23 +218,46 @@ def test_demo_file_pass(self):
216218
self.assertEqual(disc_rate.rates.max(), 0.02)
217219

218220

219-
class TestWriter(unittest.TestCase):
220-
"""Test excel reader for discount rates"""
221+
class TestWriteRead(unittest.TestCase):
222+
"""Test file write read cycle for discount rates"""
223+
224+
@classmethod
225+
def setUpClass(cls):
226+
cls._td = TemporaryDirectory()
227+
cls.tempdir = Path(cls._td.name)
228+
229+
@classmethod
230+
def tearDownClass(cls):
231+
cls._td.cleanup()
221232

222-
def test_write_read_pass(self):
233+
def test_write_read_excel_pass(self):
223234
"""Read demo excel file."""
224235
years = np.arange(1950, 2150)
225236
rates = np.ones(years.size) * 0.03
226237
disc_rate = DiscRates(years=years, rates=rates)
227238

228-
file_name = CONFIG.disc_rates.test_data.dir().joinpath('test_disc.xlsx')
239+
file_name = self.tempdir.joinpath('test_disc.xlsx')
229240
disc_rate.write_excel(file_name)
230241

231242
disc_read = DiscRates.from_excel(file_name)
232243

233244
self.assertTrue(np.array_equal(disc_read.years, disc_rate.years))
234245
self.assertTrue(np.array_equal(disc_read.rates, disc_rate.rates))
235246

247+
def test_write_read_csv_pass(self):
248+
"""Write and read csv file."""
249+
years = np.arange(1950, 2150)
250+
rates = np.ones(years.size) * 0.03
251+
disc_rate = DiscRates(years=years, rates=rates)
252+
253+
file_name = self.tempdir.joinpath('test_disc.csv')
254+
disc_rate.write_csv(file_name)
255+
256+
disc_read = DiscRates.from_csv(file_name)
257+
258+
self.assertTrue(np.array_equal(disc_read.years, disc_rate.years))
259+
self.assertTrue(np.array_equal(disc_read.rates, disc_rate.rates))
260+
236261

237262
# Execute Tests
238263
if __name__ == "__main__":
@@ -243,5 +268,5 @@ def test_write_read_pass(self):
243268
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestNetPresValue))
244269
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestReaderExcel))
245270
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestReaderMat))
246-
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestWriter))
271+
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestWriteRead))
247272
unittest.TextTestRunner(verbosity=2).run(TESTS)

0 commit comments

Comments
 (0)