Skip to content

Commit 4fe6813

Browse files
committed
major bug fixes with indexing and transformation methods. Added feature to calculate indicators regional totals without having to specify intermediate and final demand extesions separately
1 parent 33b40c3 commit 4fe6813

File tree

9 files changed

+153
-258
lines changed

9 files changed

+153
-258
lines changed

pycirk/fundamental_operations.py

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def A(inter_coef, D):
129129
Total requirement multipliers
130130
A = Z * D
131131
"""
132-
return np.matmul(inter_coef, D)
132+
return inter_coef @ D
133133

134134
def L(A):
135135
"""
@@ -157,7 +157,7 @@ def Z(inter_coef, D, diag_q):
157157
Intermediates
158158
Z = inter_coef * D * diag(q)
159159
"""
160-
return np.matmul(inter_coef, D) @ diag_q
160+
return inter_coef @ D @ diag_q
161161

162162
class IOT:
163163
"""
@@ -170,7 +170,7 @@ def x(Z, Y):
170170
"""
171171
total product output s the sum of Si and y
172172
"""
173-
return np.sum(np.array(Z), axis=1) + np.sum(np.array(Y), axis=1)
173+
return np.sum(Z, axis=1) + np.sum(Y, axis=1)
174174

175175
def B(R, inv_diag_x):
176176
"""
@@ -189,7 +189,7 @@ def x_IAy(L, y):
189189
Total product ouput
190190
x = inv(I - A) * yi
191191
"""
192-
return np.dot(L, y)
192+
return L @ y
193193

194194
def Z(A, diag_x):
195195
"""
@@ -257,7 +257,7 @@ def IOT(Z, Y, W, E, R, M):
257257
x = Operations.IOT.x_IAy(L, y)
258258

259259
ver_base = Operations.verifyIOT(Z, Y, E)
260-
260+
261261
return {"A": A,
262262
"Z": Z,
263263
"L": L,
@@ -277,17 +277,13 @@ def IOT(Z, Y, W, E, R, M):
277277

278278
def calculate_characterized(data):
279279

280-
data.Cr_E = data.Cr_E_k @ np.array(data.E)
281-
data.Cr_M = data.Cr_M_k @ np.array(data.M)
282-
data.Cr_R = data.Cr_R_k @ np.array(data.R)
283-
data.Cr_W = data.Cr_W_k @ np.array(data.W)
284-
285-
data.Cr_EY = data.Cr_E_k @ np.array(data.EY)
286-
data.Cr_MY = data.Cr_M_k @ np.array(data.MY)
287-
data.Cr_RY = data.Cr_R_k @ np.array(data.RY)
288-
289-
data.Cr_tot_E = data.Cr_E.sum(axis=1) + data.Cr_EY.sum(axis=1)
290-
data.Cr_tot_M = data.Cr_M.sum(axis=1) + data.Cr_MY.sum(axis=1)
291-
data.Cr_tot_R = data.Cr_R.sum(axis=1) + data.Cr_RY.sum(axis=1)
280+
data.Cr_E = data.Cr_E_k @ data.E
281+
data.Cr_M = data.Cr_M_k @ data.M
282+
data.Cr_R = data.Cr_R_k @ data.R
283+
data.Cr_W = data.Cr_W_k @ data.W
284+
285+
data.Cr_EY = data.Cr_E_k @ data.EY
286+
data.Cr_MY = data.Cr_M_k @ data.MY
287+
data.Cr_RY = data.Cr_R_k @ data.RY
292288

293289
return data

pycirk/labels.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,40 @@ def get_unique_labels(self, dataframe_of_labels, for_units=True):
6464
else:
6565
organize[keys] = self.list_of_something(labels)
6666

67-
count = max(len(labels) for keys, labels in organize.items())
68-
organize["count"] = count
69-
67+
try:
68+
organize["count"] = len(organize["synonym"])
69+
except KeyError:
70+
organize["count"] = len(organize["characterization"])
71+
7072
return Munch(organize)
7173

7274
def organize_unique_labels(self, directory):
7375

74-
labels = self.load_labels(directory)
75-
76-
for l, v in labels.items():
77-
labels[l] = Munch(v)
76+
lbl = self.load_labels(directory)
7877

79-
labels = Munch(labels)
80-
81-
labels.products = self.get_unique_labels(labels.prod)
82-
labels.industries = self.get_unique_labels(labels.ind)
78+
self.product_labels = self.get_unique_labels(lbl["prod"])
79+
try:
80+
self.industry_labels = self.get_unique_labels(lbl["ind"])
81+
except AttributeError:
82+
pass
83+
84+
try:
85+
self.country_labels = self.product_labels.country_code
86+
except Exception:
87+
pass
8388

84-
labels.primary = self.get_unique_labels(labels.primary)
85-
labels.fin_dem = self.get_unique_labels(labels.fin_dem)
89+
self.region_labels = self.product_labels.region
8690

87-
labels.emis = self.get_unique_labels(labels.emis, False)
88-
labels.res = self.get_unique_labels(labels.res, False)
89-
labels.mat = self.get_unique_labels(labels.mat, False)
90-
labels.car_emis = self.get_unique_labels(labels.car_emis, False)
91-
labels.car_res = self.get_unique_labels(labels.car_res, False)
92-
labels.car_mat = self.get_unique_labels(labels.car_mat, False)
93-
labels.car_prim = self.get_unique_labels(labels.car_prim, False)
91+
self.W_labels = self.get_unique_labels(lbl["primary"])
92+
self.Y_labels = self.get_unique_labels(lbl["fin_dem"])
93+
self.E_labels = self.get_unique_labels(lbl["emis"], False)
94+
self.R_labels = self.get_unique_labels(lbl["res"], False)
95+
self.M_labels = self.get_unique_labels(lbl["mat"], False)
96+
self.Cr_E_labels = self.get_unique_labels(lbl["car_emis"], False)
97+
self.Cr_R_labels = self.get_unique_labels(lbl["car_res"], False)
98+
self.Cr_M_labels = self.get_unique_labels(lbl["car_mat"], False)
99+
self.Cr_W_labels = self.get_unique_labels(lbl["car_prim"], False)
94100

95-
return labels
96101

97102
def load_labels(self, directory):
98103

@@ -278,7 +283,7 @@ def identify_labels(self, M_name):
278283

279284
attr_name = name + name_2 + "_labels"
280285
row_labels = eval("self." + attr_name)
281-
286+
282287
no_row_labs = row_labels.count
283288
no_reg_labs = len(reg_labels)
284289
no_col_labs = column_labels.count

pycirk/make_scenarios.py

Lines changed: 19 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def make_counterfactuals(data, scen_no, scen_file, labels):
4141
An object contaning a mofified IO system
4242
"""
4343
# set basic data and variables
44-
44+
print(f"Scenario {scen_no} started")
4545
data = deepcopy(data)
4646

4747
x_ = ops.IOT.x(data.Z, data.Y)
@@ -65,13 +65,15 @@ def make_counterfactuals(data, scen_no, scen_file, labels):
6565
inv_diag_x_int = np.diag(ops.inv(ops.IOT.x(data.Z, data.Y)))
6666

6767
A = ops.IOT.A(data.Z, inv_diag_x_int)
68+
6869
data.A = counterfactual(scen_file, scen_no, A, "A", labels)
6970

7071
data.Y = counterfactual(scen_file, scen_no, data.Y, "Y", labels)
7172

7273
L = ops.IOT.L(data.A)
7374

7475
x_new = ops.IOT.x_IAy(L, data.Y.sum(1))
76+
7577
diag_x_new = np.diag(x_new)
7678

7779
diag_yj_new = np.diag(data.Y.sum(axis=0))
@@ -107,13 +109,13 @@ def make_counterfactuals(data, scen_no, scen_file, labels):
107109
data.E = counterfactual(scen_file, scen_no, data.E, "E", labels)
108110
data.R = counterfactual(scen_file, scen_no, data.R, "R", labels)
109111
data.M = counterfactual(scen_file, scen_no, data.M, "M", labels)
110-
111112
# Apply policy to final demand extension coefficient matrices
112113
data.EY = counterfactual(scen_file, scen_no, data.EY, "EY", labels)
113114
data.RY = counterfactual(scen_file, scen_no, data.RY, "RY", labels)
114115
data.MY = counterfactual(scen_file, scen_no, data.MY, "MY", labels)
115116

116-
# print((1-np.sum(x_)/np.sum(x_new))*100)
117+
#print((1-np.sum(x_)/np.sum(x_new))*100)
118+
print(f"Scenario {scen_no} completed")
117119

118120
return data
119121

@@ -147,8 +149,7 @@ def counterfactual(scen_file, scen_no, M, M_name, labels):
147149
elif scen_no.startswith("scenario_"):
148150
pass
149151
else:
150-
raise KeyError("only integer or explicit name (scenario_x)" +
151-
"are allowed")
152+
raise KeyError("only integer or explicit name (scenario_x) are allowed")
152153

153154

154155
scenario = pd.read_excel(scen_file, sheet_name=scen_no, header=1, index=None)
@@ -339,7 +340,6 @@ def counterfactual_engine(M, inter_sets, subs=False, copy=False):
339340

340341
int4 = inter_sets["at2"]
341342
int4 = basic_add(int3, int4)
342-
343343
M[np.ix_(i, g)] = int4
344344

345345
if subs is True:
@@ -422,7 +422,7 @@ def make_new(filtered_changes, M, M_name, labels):
422422
try:
423423
change_type = entry.change_type
424424
ide = entry.identifier # used during debugging
425-
425+
426426
# Collecting the specified coordinates for the intevention
427427
# coordinates for region and category
428428
# Row items (i) => Supplied category or extension category
@@ -433,11 +433,14 @@ def make_new(filtered_changes, M, M_name, labels):
433433
cat_d = sing_pos(entry.cat_d, column_labels)
434434
# Identify coordinates
435435
orig_coor = coord(cat_o, reg_o, no_reg_labs, no_row_labs)
436+
#print(f"row\n ide: {ide}, row: {entry.reg_o}, {entry.cat_o}, {orig_coor}")
436437
dest_coor = coord(cat_d, reg_d, no_reg_labs, no_col_labs)
438+
#print(f"columns\n ide: {ide}, column: {entry.reg_d}, {entry.cat_d}, {dest_coor}")
439+
437440
# organize main changes
438441
kt1 = {"kt": entry.kt1, "kp": entry.kp1}
439442
kt2 = {"kt": entry.kt2, "kp": entry.kp2}
440-
443+
441444
intervention = {"change_type": change_type,
442445
"ide": ide,
443446
"i": orig_coor,
@@ -447,32 +450,32 @@ def make_new(filtered_changes, M, M_name, labels):
447450
"at1": entry.at1,
448451
"at2": entry.at2,
449452
}
450-
453+
451454
substitution = False
452455
copy = False
453-
456+
454457
# the following is only relevant for susbtitution
455458
if "x" in [entry.Sub, entry.Copy]:
456-
459+
457460
sub_reg_o = sing_pos(entry.reg_o_sc, reg_labels)
458461
sub_cat_o = sing_pos(entry.cat_o_sc, row_labels)
459-
462+
460463
# Column items => Consumption / manufacturing activity
461464
sub_reg_d = sing_pos(entry.reg_d_sc, reg_labels)
462465
sub_cat_d = sing_pos(entry.cat_d_sc, column_labels)
463-
466+
464467
# Translate coordinates from str to numerical position
465468
sub_orig_coor = coord(sub_cat_o, sub_reg_o, no_reg_labs, no_row_labs)
466469
sub_dest_coor = coord(sub_cat_d, sub_reg_d, no_reg_labs, no_col_labs)
467-
470+
468471
intervention["swk"] = entry.swk
469472
intervention["i1"] = sub_orig_coor
470473
intervention["g1"] = sub_dest_coor
471474
intervention["sk1"] = entry.sk1
472475
intervention["sk2"] = entry.sk2
473476
intervention["sk3"] = entry.sk3
474477
intervention["sk4"] = entry.sk4
475-
478+
476479
if entry.Copy == "x":
477480
copy = True
478481
elif entry.Sub == "x":
@@ -481,112 +484,5 @@ def make_new(filtered_changes, M, M_name, labels):
481484
raise ValueError(f"Check in this entry for potential coordinate errors in your scenario settings:\n{entry} ")
482485

483486
M = counterfactual_engine(M, intervention, substitution, copy)
484-
487+
485488
return M
486-
487-
# =============================================================================
488-
# =============================================================================
489-
# # Here I put work that I started but I still need to finish
490-
# =============================================================================
491-
# =============================================================================
492-
# =============================================================================
493-
#
494-
#
495-
# def make_counterfactuals_SUT(data, scen_no, scen_file, labels):
496-
# """
497-
# Calculate all the counterfactual SUT matrices
498-
#
499-
# Parameters
500-
# ----------
501-
# data : obj
502-
# An object containing all necessary matrices of the SUT system
503-
#
504-
# scen_no : int
505-
# the identification number of the scenario to reference in scen_file
506-
#
507-
# scen_file : str
508-
# the directory where the scenarios.xlsx file is store
509-
#
510-
# labels : obj
511-
# an object containing all labels for the SUT matrices
512-
#
513-
# Outputs
514-
# -------
515-
# An object contaning a mofified SUT system
516-
# """
517-
#
518-
# met = ops.PxP_ITA_MSC
519-
#
520-
# w = ops.IOT.B(data.W, data.inv_diag_g) # Primary input coef
521-
# e = ops.IOT.B(data.E, data.inv_diag_g) # emissions extension coef
522-
# r = ops.IOT.B(data.R, data.inv_diag_g) # Resources extension coef
523-
# m = ops.IOT.B(data.M, data.inv_diag_g) # Materials extension coef
524-
# S = met.S(data.U, data.inv_diag_g) # industry coefficients for intermediate use table
525-
#
526-
# # Start first from a supply approach
527-
# # Supply matrix counterfactual
528-
# data.V = counterfactual(scen_file, scen_no, data.V, "V", labels)
529-
# # new total industry output
530-
# g1 = np.sum(data.V, axis=0)
531-
# # industry use coefficients counterfactual
532-
# S_ = counterfactual(scen_file, scen_no, S, "S", labels)
533-
#
534-
# data.U = counterfactual(scen_file, scen_no, S_ @ np.diag(g1), "U", labels) # industry use transactions counterfactual
535-
#
536-
# W_ = np.array(ops.IOT.R(w, np.diag(g1)))
537-
#
538-
# g2 = np.array(W_[:9].sum(0)) + data.U.sum(0) # recalculate total industry output
539-
#
540-
# g_dif = np.multiply(g2, ops.inv(g1))*100 # calculate the difference between original and new total industry input
541-
#
542-
# # print([round((1-l)*100,4) for l in g_dif if 1-l>.5e-3 and l!=0])
543-
# q2 = np.sum(data.U, axis=1) + np.sum(data.Y, axis=1)
544-
#
545-
# # updating the supply table to match the new total industry input
546-
# D = met.D(data.V, np.diag(ops.inv(data.V.sum(1))))
547-
# data.V = D @ np.diag(q2)
548-
#
549-
# q1 = np.sum(data.V, axis=0) # total product output
550-
#
551-
# q_dif = np.multiply(q2, ops.inv(q1))
552-
#
553-
# g1 = np.sum(data.V, axis=1)
554-
#
555-
# data.E = met.R(e, np.diag(x))
556-
#
557-
# data.R = met.R(r, np.diag(x))
558-
#
559-
# data.M = met.R(m, np.diag(x))
560-
#
561-
#
562-
# return(IOT)
563-
# def balancing_operation(V, U, Y, W):
564-
# """
565-
# Re-balancing of supply-use tables after data changes
566-
#
567-
# Parameters
568-
# ----------
569-
# V (supply) : numpy.array
570-
#
571-
# U (use) : numpy.array
572-
#
573-
# Y (final_demand) : numpy.array
574-
#
575-
# W (primary_inputs) : numpy.array
576-
#
577-
# Output
578-
# ------
579-
# output : dict
580-
#
581-
# It outputs a dictionary containing a re-balanced supply-use tables system
582-
# where:
583-
# V = supply table
584-
#
585-
# U = use table
586-
#
587-
# Y = final demand
588-
#
589-
# W = primary inputs
590-
#
591-
# """
592-
# =============================================================================

0 commit comments

Comments
 (0)