mrio-toolbox 1.0.0__py3-none-any.whl → 1.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mrio-toolbox might be problematic. Click here for more details.

Files changed (59) hide show
  1. mrio_toolbox/__init__.py +18 -2
  2. mrio_toolbox/_parts/_Axe.py +95 -37
  3. mrio_toolbox/_parts/_Part.py +264 -70
  4. mrio_toolbox/_parts/__init__.py +4 -0
  5. mrio_toolbox/_parts/part_operations.py +24 -17
  6. mrio_toolbox/extractors/__init__.py +20 -0
  7. mrio_toolbox/extractors/downloaders.py +36 -0
  8. mrio_toolbox/extractors/emerging/__init__.py +3 -0
  9. mrio_toolbox/extractors/emerging/emerging_extractor.py +117 -0
  10. mrio_toolbox/extractors/eora/__init__.py +3 -0
  11. mrio_toolbox/extractors/eora/eora_extractor.py +132 -0
  12. mrio_toolbox/extractors/exiobase/__init__.py +3 -0
  13. mrio_toolbox/extractors/exiobase/exiobase_extractor.py +270 -0
  14. mrio_toolbox/extractors/extractors.py +79 -0
  15. mrio_toolbox/extractors/figaro/__init__.py +3 -0
  16. mrio_toolbox/extractors/figaro/figaro_downloader.py +280 -0
  17. mrio_toolbox/extractors/figaro/figaro_extractor.py +187 -0
  18. mrio_toolbox/extractors/gloria/__init__.py +3 -0
  19. mrio_toolbox/extractors/gloria/gloria_extractor.py +202 -0
  20. mrio_toolbox/extractors/gtap11/__init__.py +7 -0
  21. mrio_toolbox/extractors/gtap11/extraction/__init__.py +3 -0
  22. mrio_toolbox/extractors/gtap11/extraction/extractor.py +129 -0
  23. mrio_toolbox/extractors/gtap11/extraction/harpy_files/__init__.py +6 -0
  24. mrio_toolbox/extractors/gtap11/extraction/harpy_files/_header_sets.py +279 -0
  25. mrio_toolbox/extractors/gtap11/extraction/harpy_files/har_file.py +262 -0
  26. mrio_toolbox/extractors/gtap11/extraction/harpy_files/har_file_io.py +974 -0
  27. mrio_toolbox/extractors/gtap11/extraction/harpy_files/header_array.py +300 -0
  28. mrio_toolbox/extractors/gtap11/extraction/harpy_files/sl4.py +229 -0
  29. mrio_toolbox/extractors/gtap11/gtap_mrio/__init__.py +6 -0
  30. mrio_toolbox/extractors/gtap11/gtap_mrio/mrio_builder.py +158 -0
  31. mrio_toolbox/extractors/icio/__init__.py +3 -0
  32. mrio_toolbox/extractors/icio/icio_extractor.py +121 -0
  33. mrio_toolbox/extractors/wiod/__init__.py +3 -0
  34. mrio_toolbox/extractors/wiod/wiod_extractor.py +143 -0
  35. mrio_toolbox/mrio.py +254 -94
  36. mrio_toolbox/msm/__init__.py +6 -0
  37. mrio_toolbox/msm/multi_scale_mapping.py +863 -0
  38. mrio_toolbox/utils/__init__.py +3 -0
  39. mrio_toolbox/utils/converters/__init__.py +3 -0
  40. mrio_toolbox/utils/converters/pandas.py +8 -6
  41. mrio_toolbox/utils/converters/xarray.py +2 -13
  42. mrio_toolbox/utils/formatting/__init__.py +0 -0
  43. mrio_toolbox/utils/formatting/formatter.py +528 -0
  44. mrio_toolbox/utils/loaders/__init__.py +4 -0
  45. mrio_toolbox/utils/loaders/_loader.py +60 -4
  46. mrio_toolbox/utils/loaders/_loader_factory.py +22 -1
  47. mrio_toolbox/utils/loaders/_nc_loader.py +37 -1
  48. mrio_toolbox/utils/loaders/_pandas_loader.py +29 -3
  49. mrio_toolbox/utils/loaders/_parameter_loader.py +61 -16
  50. mrio_toolbox/utils/savers/__init__.py +3 -0
  51. mrio_toolbox/utils/savers/_path_checker.py +25 -7
  52. mrio_toolbox/utils/savers/_to_folder.py +6 -1
  53. mrio_toolbox/utils/savers/_to_nc.py +26 -18
  54. {mrio_toolbox-1.0.0.dist-info → mrio_toolbox-1.1.1.dist-info}/METADATA +10 -6
  55. mrio_toolbox-1.1.1.dist-info/RECORD +59 -0
  56. {mrio_toolbox-1.0.0.dist-info → mrio_toolbox-1.1.1.dist-info}/WHEEL +1 -1
  57. mrio_toolbox-1.0.0.dist-info/RECORD +0 -26
  58. {mrio_toolbox-1.0.0.dist-info → mrio_toolbox-1.1.1.dist-info/licenses}/LICENSE +0 -0
  59. {mrio_toolbox-1.0.0.dist-info → mrio_toolbox-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,3 @@
1
+ """
2
+ This module provides utility functions and classes for loading, saving and converting MRIO tables.
3
+ """
@@ -1,2 +1,5 @@
1
+ """
2
+ This module provides utility functions for converting Part objects to pandas DataFrames or xarray DataArrays.
3
+ """
1
4
  from . import xarray
2
5
  from . import pandas
@@ -10,15 +10,17 @@ def to_pandas(part):
10
10
 
11
11
  Only applicable to Parts objects with 1 or 2 dimensions.
12
12
  """
13
- if part.ndim>2:
14
- raise ValueError(f"Cannot convert a Part with {part.ndim} dimensions to DataFrame.")
15
- elif part.ndim==2:
13
+ if part.ndim==2:
16
14
  return pd.DataFrame(part.data,
17
15
  index = part.axes[0].label(True),
18
16
  columns = part.axes[1].label(True))
19
- else:
20
- return pd.DataFrame(part.data,index = part.axes[0].label(True)
21
- )
17
+ if part.ndim==1:
18
+ return pd.DataFrame(part.data,index = part.axes[0].label(True))
19
+ try:
20
+ return to_pandas(part.squeeze())
21
+ except:
22
+ raise ValueError(f"Cannot convert a Part with {part.ndim} dimensions to DataFrame.")
23
+
22
24
 
23
25
  def make_part(df,name="from_df",
24
26
  label_detection=False,
@@ -17,7 +17,7 @@ def to_DataArray(part):
17
17
  xr.DataArray
18
18
  Corresponding DataArray
19
19
  """
20
- developed = part.develop()
20
+ developed = part.develop(squeeze=False) #Force non-squeeze to keep dimensions
21
21
  old_dims = part.get_dimensions()
22
22
  new_dims = developed.get_dimensions()
23
23
  if old_dims != new_dims:
@@ -87,14 +87,7 @@ def make_part(data,**kwargs):
87
87
  for key in data.dims:
88
88
  label = dict()
89
89
  index = data.indexes[key]
90
- if isinstance(index,pd.MultiIndex):
91
- for i in index.nlevels:
92
- name = index.names[i]
93
- if name is None:
94
- name = i
95
- label[str(name)] = index.get_level_values(i).tolist()
96
- else:
97
- label[index.name] = index.values.tolist()
90
+ label[index.name] = index.values.tolist()
98
91
  labels.append(label)
99
92
  part_data["name"] = name
100
93
  part_data["labels"] = labels
@@ -127,10 +120,6 @@ def make_mrio(data,**kwargs):
127
120
 
128
121
  labels = dict()
129
122
  for coord in data.coords:
130
- #Uncompress MultiIndex data if needed
131
- if "compress" in data[coord].attrs:
132
- import cf_xarray as cfxr
133
- data = cfxr.decode_compress_to_multi_index(data,coord)
134
123
  labels[coord] = data[coord].values.tolist()
135
124
  mrio_data["labels"] = labels
136
125
  mrio_data["groupings"] = kwargs.get("groupings",dict())
File without changes
@@ -0,0 +1,528 @@
1
+ """
2
+ Format MRIO tables to meet specific requirements
3
+ """
4
+
5
+
6
+ import os
7
+ import sys
8
+ import yaml
9
+ import numpy as np
10
+ import logging as log
11
+
12
+ #from mrio_toolbox import MRIO
13
+
14
+ log = log.getLogger(__name__)
15
+
16
+ def reallocate_negatives(mrio,
17
+ final_demand="y",
18
+ value_added="va",
19
+ category_fd=None,
20
+ category_va=None,
21
+ destination_fd = -1,
22
+ destination_va = -1,
23
+ from_fd=True,
24
+ from_va=True,
25
+ validate_intermediates=False):
26
+ """Reallocate negative values between final demand and value added parts
27
+
28
+ Negative values might interfere with some MRIO operation.
29
+ This function reallocates negative values from final demand to value added parts and vice versa.
30
+
31
+ Parameters
32
+ ----------
33
+ mrio : MRIO instance
34
+ Instance on which the operation applies
35
+ final_demand : str, optional
36
+ Name of the final demand part. The default is "y"
37
+ value_added : str, optional
38
+ Name of the value added part. The default is "va"
39
+ origin_fd : list of str, optional
40
+ List of final demand labels that are transferable. The default is None.
41
+ If no label is given, all negative values are transferred.
42
+ origin_va : list of str, optional
43
+ List of value added labels that are transferable. The default is None.
44
+ If no label is given, all negative values are transferred.
45
+ destination_fd : str, optional
46
+ Final demand categories to which negative values are transferred.
47
+ The default is -1, i.e. the last final demand category.
48
+ destination_va : str, optional
49
+ Value added category to which negative values are transferred.
50
+ The default is -1, i.e. the last value added category.
51
+ from_fd : bool, optional
52
+ Whether to reallocate from final demand to value added. The default is True.
53
+ from_va : bool, optional
54
+ Whether to reallocate from value added to final demand. The default is True.
55
+ validate_intermediates : bool, optional
56
+ Whether to double check the validity of intermediate use,
57
+ i.e., that intermediate inputs demand do not exceed the total output.
58
+ See the corresponding function's documentation
59
+
60
+ """
61
+ if final_demand not in mrio.parts.keys():
62
+ log.error(f"Part {final_demand} not found in MRIO. Cannot reallocate final demand.")
63
+ raise ValueError(f"Part {final_demand} not found in MRIO. Cannot reallocate final demand.")
64
+ if value_added not in mrio.parts.keys():
65
+ log.error(f"Part {value_added} not found in MRIO. Cannot reallocate final demand.")
66
+ raise ValueError(f"Part {value_added} not found in MRIO. Cannot reallocate final demand.")
67
+
68
+ log.info(f"Reallocate final values between {final_demand} and {value_added}")
69
+
70
+ fd = mrio.parts[final_demand]
71
+ va = mrio.parts[value_added]
72
+
73
+ ###Extract the negative value added and replace them by
74
+ if from_fd:
75
+ log.info("Remove negatives from the final demand")
76
+ selectable_fd = fd
77
+ #Select transferrable data
78
+ if category_fd is not None and fd.axes[1].ndim==2:
79
+ selectable_fd = fd["all",["all",category_fd]]
80
+
81
+ loc_negs_fd = np.where(selectable_fd.data<0)
82
+ neg_fd = selectable_fd.data[loc_negs_fd]
83
+ #Sum over importing countries and final demand categories
84
+ selectable_fd.data[loc_negs_fd] = 0
85
+ if category_fd is not None and fd.axes[1].ndim==2:
86
+ fd["all",["all",category_fd]] = selectable_fd
87
+
88
+
89
+ if from_va:
90
+ log.info("Remove negatives from the value added")
91
+ selectable_va = va
92
+ #Select transferrable data
93
+ if category_va is not None:
94
+ if selectable_va.ndim==1:
95
+ log.warning("The value added part is aggregated. The argument 'category_va' will be ignored.")
96
+ else:
97
+ selectable_va = va[category_va]
98
+
99
+ loc_negs_va = np.where(selectable_va.data<0)
100
+ neg_va = selectable_va.data[loc_negs_va].copy()
101
+ selectable_va.data[loc_negs_va] = 0
102
+ if neg_va.ndim>1:
103
+ #Sum over va categories if needed
104
+ neg_va = neg_va.sum(axis=0)
105
+
106
+ if category_va is not None and selectable_va.ndim>1:
107
+ va[category_va] = selectable_va
108
+
109
+ ###Add the negative values to the other part
110
+
111
+ if from_fd:
112
+ log.info("Add final demand negatives to the value added")
113
+ for value,position in zip(neg_fd,loc_negs_fd[0]):
114
+ if va.ndim==2:
115
+ va[[destination_va],[position]] += -value
116
+ else:
117
+ va[[position]] += -value
118
+
119
+ if from_va:
120
+ log.info("Add value added negatives to the final demand")
121
+
122
+ #Negative value added are only added to the domestic final demand
123
+ for value,position in zip(neg_va,loc_negs_va[-1]):
124
+ country = position // fd.axes[0].multipliers[fd.axes[0].dimensions[0]]
125
+ if fd.axes[1].ndim==1:
126
+ fd[[[position],[country]]] += -value
127
+ else:
128
+ fd[position,[[country],[destination_fd]]] += -value
129
+
130
+ if validate_intermediates:
131
+ mrio.validate_intermediates()
132
+
133
+ def adjust_intermediates(mrio,
134
+ final_demand = "y",
135
+ inter_industry = "t",
136
+ destination = -1,
137
+ save_gross_output=True):
138
+ """
139
+ Ensures that intermediate use is always less than gross output
140
+
141
+ This is required to avoid negative value added as residual.
142
+ The domestic final demand is adjusted to make sure gross output is larger than intermediate use.
143
+
144
+ Parameters
145
+ ----------
146
+ mrio : MRIO instance
147
+ Instance on which the operation applies
148
+ final_demand : str, optional
149
+ Name of the final demand part. The default is "y"
150
+ inter_industry : str, optional
151
+ Name of the inter-industry part. The default is "t"
152
+ destination : str, optional
153
+ Final demand categories to which negative values are transferred.
154
+ The default is -1, i.e. the last final demand category.
155
+ """
156
+ if final_demand not in mrio.parts.keys():
157
+ log.error(f"Part {final_demand} not found in MRIO. Cannot readjust intermediates.")
158
+ raise ValueError(f"Part {final_demand} not found in MRIO. Cannot readjust intermediates.")
159
+ if inter_industry not in mrio.parts.keys():
160
+ log.error(f"Part {inter_industry} not found in MRIO. Cannot readjust intermediates.")
161
+ raise ValueError(f"Part {inter_industry} not found in MRIO. Cannot readjust intermediates.")
162
+
163
+ log.info(f"Adjust intermediates in parts {inter_industry} and {final_demand}")
164
+ fd = mrio.parts[final_demand]
165
+ t = mrio.parts[inter_industry]
166
+ original_x = t.sum(1) + fd.sum(1)
167
+ residual = original_x - t.sum(0)
168
+
169
+ loc_negs = np.where(residual.data<0)
170
+ negs = residual.data[loc_negs]
171
+
172
+ for value,position in zip(negs,loc_negs[-1]):
173
+ country = position // fd.axes[0].multipliers[fd.axes[0].dimensions[0]]
174
+ if fd.axes[1].ndim==1:
175
+ fd[[[position],[country]]] += -value
176
+ else:
177
+ fd[position,[[country],[destination]]] += -value
178
+
179
+ if save_gross_output:
180
+ if not isinstance(save_gross_output,str):
181
+ save_gross_output = "x"
182
+ mrio.parts[save_gross_output] = t.sum(1) + fd.sum(1)
183
+
184
+ def fill_empty_rows(
185
+ mrio,
186
+ final_demand = "y",
187
+ inter_industry = "t",
188
+ target = -1,
189
+ fill_value=0.5,
190
+ save_gross_output = True
191
+ ):
192
+ """
193
+ Insert fill values in empty rows
194
+
195
+ This avoids any issue with missing data (e.g. for the Leontief inversion)
196
+ The fill value is inserted on the diagonal of empty rows in the inter-industry matrix
197
+ and as domestic consumption for final demand,
198
+ such that it does not interfere with the rest of the table.
199
+ The fill_value 1 must be avoided, as it conflicts with the Leontief inversion.
200
+ Note that the fill value slightly changes the aggregate.
201
+ """
202
+ if inter_industry not in mrio.parts.keys():
203
+ log.error(f"Part {inter_industry} not found in MRIO. Cannot fill the empty rows.")
204
+ raise ValueError(f"Part {inter_industry} not found in MRIO. Cannot fill the empty rows.")
205
+ if final_demand not in mrio.parts.keys():
206
+ log.error(f"Part {final_demand} not found in MRIO. Cannot fill the empty rows.")
207
+ raise ValueError(f"Part {final_demand} not found in MRIO. Cannot fill the empty rows.")
208
+
209
+ log.info(f"Fill empty rows in parts {inter_industry} and {final_demand}")
210
+ t = mrio.parts[inter_industry]
211
+ y = mrio.parts[final_demand]
212
+
213
+ x = t.sum(1) + y.sum(1)
214
+ zeros = np.where(x.data==0)
215
+ sectors = t.axes[0].labels[t.axes[0].dimensions[1]]
216
+ for zero in zeros[0]:
217
+
218
+ t[[zero],[zero]] = fill_value
219
+ country = zero // y.axes[0].multipliers[y.axes[0].dimensions[0]]
220
+ sector = sectors[zero % y.axes[0].multipliers[y.axes[0].dimensions[0]]]
221
+ log.info(f"Fill empty row {zero}: {mrio.countries[country]}, {sector}")
222
+ if y.axes[1].ndim==1:
223
+ y[[zero],[country]] = fill_value
224
+ else:
225
+ y[[zero],[[country],[target]]] = fill_value
226
+
227
+ if save_gross_output:
228
+ if not isinstance(save_gross_output,str):
229
+ save_gross_output = "x"
230
+ mrio.parts[save_gross_output] = t.sum(1) + y.sum(1)
231
+
232
+ def balance_va(
233
+ mrio,
234
+ final_demand="y",
235
+ value_added="va",
236
+ inter_industry="t",
237
+ save_as_category=False,
238
+ category="residual"
239
+ ):
240
+ """Fill residuals in the value added part.
241
+
242
+ This makes sure the balance is respected.
243
+ If save_as_category is False, the value_added part is overwritten
244
+ in order to balance the table.
245
+ Otherwise, the residuals are stored in the given category.
246
+ If a non-existing category is provided, it is added to the existing va labels.
247
+
248
+ Parameters
249
+ ----------
250
+ mrio : MRIO instance
251
+ The MRIO instance to format.
252
+ final_demand : str
253
+ The name of the final demand part.
254
+ inter_industry : str
255
+ The name of the inter-industry part.
256
+ value_added : str
257
+ The name of the value added part.
258
+ save_as_category : bool
259
+ Whether to save the residuals in a category.
260
+ Otherwise, the value added is defined as the full residual
261
+ category : str
262
+ Name of the category under which the residual is stored.
263
+ If the category does not exist, it is created.
264
+ If the value added was flat, a va_labs dimension is added.
265
+ """
266
+ if inter_industry not in mrio.parts.keys():
267
+ log.error(f"Part {inter_industry} not found in MRIO. Cannot fill the empty rows.")
268
+ raise ValueError(f"Part {inter_industry} not found in MRIO. Cannot fill the empty rows.")
269
+ if final_demand not in mrio.parts.keys():
270
+ log.error(f"Part {final_demand} not found in MRIO. Cannot fill the empty rows.")
271
+ raise ValueError(f"Part {final_demand} not found in MRIO. Cannot fill the empty rows.")
272
+
273
+ log.info(f"Balance value added in part {value_added}")
274
+ t,y = mrio.parts[inter_industry], mrio.parts[final_demand]
275
+
276
+ x = t.sum(1) + y.sum(1)
277
+
278
+ if not save_as_category:
279
+ log.info(f"Write balanced value added in part {value_added}")
280
+ mrio.parts[value_added] = x - t.sum(0)
281
+ return
282
+
283
+ log.info(f"Save residuals in category '{category}' of part {value_added}")
284
+ if value_added not in mrio.parts.keys():
285
+ log.error(f"Part {value_added} not found in MRIO. Cannot fill the empty rows.")
286
+ raise ValueError(f"Part {value_added} not found in MRIO. Cannot fill the empty rows.")
287
+ va = mrio.parts[value_added]
288
+ residual = x - t.sum(0) - va.sum(0)
289
+
290
+ #Adjust va dimensions
291
+ if va.ndim == 1:
292
+ mrio.add_dimensions({
293
+ "va_labs" : ["original_va", category]
294
+ })
295
+ new_va = mrio.new_part(
296
+ name="balanced_va",
297
+ data = np.zeros((2,va.shape[0])),
298
+ dims = ["va_labs", va.axes[0].dimensions]
299
+ )
300
+ new_va["original_va"] = va
301
+
302
+ if category not in va.axes[0].labels[va.axes[0].dimensions[0]]:
303
+ va_labs = va.axes[0].dimensions[0]
304
+ mrio.add_labels([category], va_labs)
305
+ va = mrio.parts[value_added] #Reload va with new labels
306
+
307
+ va[category] += residual
308
+
309
+ def compute_technical_coefficients(mrio,
310
+ name="a",
311
+ inter_industry="t",
312
+ final_demand = "y"
313
+ ):
314
+ """
315
+ Compute the technical coefficients matrix.
316
+
317
+ This is the inter-industry matrix normalized by the gross output.
318
+
319
+ Parameters
320
+ ----------
321
+ mrio : MRIO
322
+ The MRIO instance to format.
323
+ name : str
324
+ The name under which the technical coefficients matrix will be stored.
325
+ The default is "a".
326
+ If no name is provided, the technical coefficients matrix is not stored and directly returned.
327
+ inter_industry : str
328
+ The name of the inter-industry matrix stored.
329
+ The default is "t".
330
+ final_demand : str
331
+ The name of the final demand matrix stored.
332
+ The default is "y".
333
+ """
334
+ if inter_industry not in mrio.parts.keys():
335
+ log.error(f"Part {inter_industry} not found in MRIO. Cannot compute the technical coefficients matrix.")
336
+ raise ValueError(f"Part {inter_industry} not found in MRIO. Cannot compute the technical coefficients matrix.")
337
+ t = mrio.parts[inter_industry]
338
+
339
+ if final_demand not in mrio.parts.keys():
340
+ log.error(f"Part {final_demand} not found in MRIO. Cannot compute the technical coefficients matrix.")
341
+ raise ValueError(f"Part {final_demand} not found in MRIO. Cannot compute the technical coefficients matrix.")
342
+ y = mrio.parts[final_demand]
343
+ x = t.sum(1) + y.sum(1)
344
+ x.data[x.data==0] = 1 #Avoid division by zero
345
+
346
+ if not name:
347
+ return t.mul((1/x).diag())
348
+
349
+ mrio.parts[name] = t.mul((1/x).diag())
350
+
351
+ def compute_leontief(mrio,
352
+ name="l",
353
+ technical_coefficients_matrix="a",
354
+ **kwargs):
355
+ """
356
+ Compute the Leontief inverse matrix.
357
+
358
+ If the technical coefficients matrix is not provided, it will be computed.
359
+
360
+ Parameters
361
+ ----------
362
+ mrio : MRIO
363
+ The MRIO instance to format.
364
+ name : str
365
+ The name under which the Leontief inverse matrix will be stored.
366
+ technical_coefficients_matrix : str
367
+ The name of the technical coefficients matrix to use.
368
+ If the matrix does not exist, it is computed and saved under the corresponding name.
369
+ If False, the technical coefficients matrix is computed but not stored.
370
+ kwargs : dict
371
+ Additional keyword arguments for the technical coefficients matrix computation.
372
+ """
373
+ if not technical_coefficients_matrix:
374
+ a = compute_technical_coefficients(mrio,
375
+ name=technical_coefficients_matrix,**kwargs)
376
+ else:
377
+ if technical_coefficients_matrix not in mrio.parts.keys():
378
+ compute_technical_coefficients(mrio, name= technical_coefficients_matrix,
379
+ **kwargs)
380
+ a = mrio.parts[technical_coefficients_matrix]
381
+ mrio.parts[name] = a.leontief_inversion()
382
+
383
+
384
+ def preprocess(
385
+ mrio,
386
+ reallocate_negatives = False,
387
+ adjust_intermediates = False,
388
+ fill_empty_rows = False,
389
+ balance_va = False,
390
+ group_parts = False,
391
+ final_demand="y",
392
+ inter_industry="t",
393
+ value_added="va",
394
+ compute_technical_coefficients = False,
395
+ compute_leontief = False,
396
+ save = False
397
+ ):
398
+ """
399
+ Preprocess MRIO data.
400
+
401
+ The following operations are available:
402
+ - reallocate_negatives:
403
+ Allocate negative final demand and value added
404
+ to the opposite member
405
+ - adjust_intermediates:
406
+ Adjust intermediate consumption values to avoid negative value added.
407
+ - fill_empty_rows:
408
+ Add empty rows in the MRIO tables, to avoid computational errors.
409
+ - balance_va:
410
+ Balance the table by adding residuals to the value added.
411
+ - group_parts:
412
+ Group parts in the MRIO tables.
413
+ - compute_technical_coefficients:
414
+ Compute the technical coefficients matrix.
415
+ - compute_leontief:
416
+ Compute the Leontief inverse matrix.
417
+
418
+ Parameters
419
+ ----------
420
+ mrio : MRIO instance
421
+ MRIO instance to preprocess.
422
+ reallocate_negatives : dict
423
+ Parameters for reallocating negative values.
424
+ adjust_intermediates : dict
425
+ Parameters for adjusting intermediate values.
426
+ fill_empty_rows : dict
427
+ Parameters for filling empty rows.
428
+ balance_va : dict
429
+ Parameters for balancing value added.
430
+ group_parts : dict
431
+ Parameters for grouping parts.
432
+ Must be set as a dictionary:
433
+ part_name : parameters for the sum operator (axes, dimension)
434
+ final_demand : str
435
+ Name of the final demand matrix.
436
+ inter_industry : str
437
+ Name of the inter-industry matrix.
438
+ value_added : str
439
+ Name of the value added matrix.
440
+ compute_technical_coefficients : bool or dict
441
+ Whether to compute the technical coefficients matrix.
442
+ If dict, optional parameters for the computation.
443
+ compute_leontief : bool or dict
444
+ Whether to compute the Leontief inverse matrix.
445
+ If dict, optional parameters for the computation.
446
+ save : dict
447
+ Parameters to save the processed MRIO instance.
448
+ Parameters for the saving process.
449
+ """
450
+ log.info("Start formatting MRIO")
451
+
452
+ if group_parts:
453
+ for part, args in group_parts.items():
454
+ log.info(f"Group part '{part}' over {args}")
455
+ mrio.parts[part] = mrio.parts[part].sum(**args)
456
+
457
+ if reallocate_negatives:
458
+ if isinstance(reallocate_negatives, bool):
459
+ reallocate_negatives = dict()
460
+ mrio.reallocate_negatives(
461
+ final_demand=final_demand,
462
+ value_added=value_added,
463
+ **reallocate_negatives
464
+ )
465
+
466
+ if fill_empty_rows:
467
+ if isinstance(fill_empty_rows, bool):
468
+ fill_empty_rows = dict()
469
+ mrio.fill_empty_rows(
470
+ final_demand=final_demand,
471
+ inter_industry=inter_industry,
472
+ **fill_empty_rows
473
+ )
474
+
475
+ if adjust_intermediates:
476
+ if isinstance(adjust_intermediates, bool):
477
+ adjust_intermediates = dict()
478
+ mrio.adjust_intermediates(
479
+ final_demand=final_demand,
480
+ inter_industry=inter_industry,
481
+ **adjust_intermediates
482
+ )
483
+
484
+ if balance_va:
485
+ if isinstance(balance_va, bool):
486
+ balance_va = dict()
487
+ mrio.balance_va(
488
+ final_demand=final_demand,
489
+ inter_industry=inter_industry,
490
+ value_added=value_added,
491
+ **balance_va
492
+ )
493
+
494
+ if compute_technical_coefficients:
495
+ if isinstance(compute_technical_coefficients, bool):
496
+ compute_technical_coefficients = dict()
497
+ mrio.compute_technical_coefficients(
498
+ inter_industry=inter_industry,
499
+ final_demand=final_demand,
500
+ **compute_technical_coefficients
501
+ )
502
+
503
+ if compute_leontief:
504
+ if isinstance(compute_leontief, bool):
505
+ compute_leontief = dict()
506
+ mrio.compute_leontief(
507
+ inter_industry=inter_industry,
508
+ final_demand=final_demand,
509
+ **compute_leontief
510
+ )
511
+
512
+ if save:
513
+ if isinstance(save, bool):
514
+ save = dict()
515
+ mrio.save(**save)
516
+
517
+ def rename_part(mrio,old_name,new_name):
518
+ """Change the name of an MRIO part"""
519
+ if old_name not in mrio.parts.keys():
520
+ raise KeyError(f"Part '{old_name}' not found in MRIO. Cannot rename it to '{new_name}'.")
521
+ log.info(f"Rename part '{old_name}' to '{new_name}'")
522
+ mrio.parts[new_name] = mrio.parts.pop(old_name)
523
+ mrio.parts[new_name].name = new_name
524
+
525
+ def rename_parts(mrio,renaming_dict):
526
+ """Change the name of a collection of MRIO parts"""
527
+ for old_name,new_name in renaming_dict.items():
528
+ rename_part(mrio,old_name,new_name)
@@ -1,3 +1,7 @@
1
+ """
2
+ This module provides utility functions and classes for loading MRIO data from various sources.
3
+ """
4
+
1
5
  from mrio_toolbox.utils.loaders._loader_factory import make_loader
2
6
 
3
7
  __all__ = ["make_loader"]