Brightway 2.5用datapackage结合Ecoinvent对比场景遇矩阵错误求助
Brightway 2.5中使用datapackage修改场景交换项时遇到非方阵错误的解决求助
我需要编写代码,在同一个包含活动和交换项的数据库下对比不同场景,每次运行时更新交换项数值。为了避免逐个用exc['amount']和exc.save()更新交换项,我知道用datapackage可以实现更高效的操作,参考相关内容编写了示例代码,但运行时出现错误:
bw2calc.errors.NonsquareTechnosphere: Technosphere matrix is not square: 1 activities (columns) and 4 products (rows).
最终我要处理50余个场景,以及包含约70个新活动的数据库,怀疑错误源于Ecoinvent与自建数据库的关联问题,求结合Ecoinvent数据库的datapackage代码示例。
环境信息
- Python 3.12.2
- Brightway 2.5相关包版本:
bw2calc 2.0.dev18 bw2data 4.0.dev46 bw2io 0.9.dev30 bw_processing 0.9.6
示例代码
import bw2data as bd import bw2io as bi import numpy as np import bw2calc as bc import bw_processing as bwp bd.projects.set_current("Save3") # ====== 导入Ecoinvent ====== if 'Ecoinvent_3.9.1_apos' in bd.databases: print("数据库已导入。") # ====== 创建数据库 ====== MyDB = bd.Database('MyDB') MyDB.register() eidb = bd.Database('Ecoinvent_3.9.1_apos') eidb.order_by='name' bio = bd.Database("biosphere3") # ====== 创建新活动 ====== Prod_Sirop = MyDB.new_activity(code='Psirop', name="糖浆生产", unit="千克", comment="基准年(2019年)的糖浆生产") Prod_Sirop.save() electricityMix_FR = bd.utils.get_node(database = 'Ecoinvent_3.9.1_apos', name = 'market for electricity, medium voltage', location = 'FR', unit = 'kilowatt hour') Prod_Sirop.new_exchange(input=electricityMix_FR.key, amount=0,unit="kWh", type="technosphere").save() market_selsNACl = bd.utils.get_node(database = 'Ecoinvent_3.9.1_apos', name = 'market for sodium chloride, powder', location = 'GLO', unit = 'kilogram') Prod_Sirop.new_exchange(input=market_selsNACl.key, amount=50000, unit="千克", type="technosphere").save() SiropProduction = 20000000 # 立方米/年 Prod_Sirop.new_exchange(input=Prod_Sirop, amount=SiropProduction, unit="立方米", type="production").save() Prod_Sirop.save() # ====== 创建datapackage ====== dp_newscenario = bwp.create_datapackage() t_indices= np.array([(electricityMix_FR.id, Prod_Sirop.id), (market_selsNACl.id, Prod_Sirop.id)], dtype=bwp.INDICES_DTYPE) t_data =np.array([2000, 4000]) # 创建新场景向量 dp_newscenario.add_persistent_vector( matrix='technosphere_matrix', indices_array=t_indices, data_array=t_data, flip_array=np.array([True, True]), name='Sc1') # ====== 执行LCI/LCIA ====== lca = bc.LCA( demand={Prod_Sirop: 1}, data_objs=[dp_newscenario], use_distributions=False, use_arrays=True, method=('ReCiPe 2016 v1.03, midpoint (H)','climate change','global warming potential (GWP1000)')) lca.lci() lca.lcia()
问题原因与修正方案
错误原因
出现非方阵错误的核心问题是:初始化LCA对象时仅传入了自定义场景的datapackage,未包含Ecoinvent、biosphere3及自建数据库的基础数据。Brightway无法获取Ecoinvent活动对应的矩阵维度信息,导致技术矩阵行/列数量不匹配。
修正后的代码示例
import bw2data as bd import numpy as np import bw2calc as bc import bw_processing as bwp bd.projects.set_current("Save3") # 加载所有必要数据库 eidb = bd.Database('Ecoinvent_3.9.1_apos') mydb = bd.Database('MyDB') bio = bd.Database("biosphere3") # 获取目标活动与Ecoinvent节点 Prod_Sirop = mydb.get(code='Psirop') electricityMix_FR = bd.utils.get_node(database='Ecoinvent_3.9.1_apos', name='market for electricity, medium voltage', location='FR', unit='kilowatt hour') market_selsNACl = bd.utils.get_node(database='Ecoinvent_3.9.1_apos', name='market for sodium chloride, powder', location='GLO', unit='kilogram') # ====== 创建场景datapackage(仅包含需要修改的交换项) ====== dp_scenario1 = bwp.create_datapackage() # 技术矩阵索引格式:(供应方ID, 需求方ID) # flip_array=True表示该交换项为消耗(对应技术矩阵中的负向值) t_indices = np.array([ (electricityMix_FR.id, Prod_Sirop.id), (market_selsNACl.id, Prod_Sirop.id) ], dtype=bwp.INDICES_DTYPE) t_data = np.array([2000, 4000]) # 场景1的新交换项数值 dp_scenario1.add_persistent_vector( matrix='technosphere_matrix', indices_array=t_indices, data_array=t_data, flip_array=np.array([True, True]), name='Scenario_1' ) # ====== 初始化LCA,传入所有基础数据与场景修改 ====== # 顺序要求:基础数据库在前,场景datapackage在后(确保修改覆盖基础值) lca = bc.LCA( demand={Prod_Sirop: 1}, data_objs=[eidb, mydb, bio, dp_scenario1], use_distributions=False, use_arrays=True, method=('ReCiPe 2016 v1.03, midpoint (H)','climate change','global warming potential (GWP1000)') ) lca.lci() lca.lcia() print(f"场景1的LCIA结果:{lca.score}") # ====== 快速切换场景示例 ====== # 创建场景2的datapackage dp_scenario2 = bwp.create_datapackage() t_data2 = np.array([3000, 5000]) dp_scenario2.add_persistent_vector( matrix='technosphere_matrix', indices_array=t_indices, data_array=t_data2, flip_array=np.array([True, True]), name='Scenario_2' ) # 重置LCA并加载新场景 lca.rebuild_lcia_data(data_objs=[eidb, mydb, bio, dp_scenario2]) lca.lci() lca.lcia() print(f"场景2的LCIA结果:{lca.score}")
关键注意事项
- 数据对象顺序:基础数据库(Ecoinvent、自建库、biosphere)必须放在场景datapackage之前,确保场景修改能覆盖基础数据。
- 索引与翻转数组:
indices_array需严格对应(供应方ID, 需求方ID),flip_array的布尔值要匹配交换项类型(技术输入一般设为True)。 - 批量场景处理:可将多个场景的datapackage存入列表,循环执行LCA计算,无需重复加载基础数据,提升效率。
内容的提问来源于stack exchange,提问作者mbess
相关产品推荐
相关产品推荐

