在 Brightway 的循环中将多个活动保存到数据库
Saving multiple activities to database in a loop in Brightway
我有一个生成数据并将其写入数据库的循环:
myDatabase = Database('myDatabase')
for i in range(10):
#some code here that generates dictionaries that can be saved as activities
myDatabase.write({('myDatabase', 'valid code'): activityDict})
这样创建的单个活动可以保存到数据库中。但是,当创建多个时,数据库的长度始终为 1,只有最后一个 activity 进入数据库。
因为我有很多非常大的数据集,所以将它们全部存储在一个字典中并一次写入数据库并不方便。
有没有办法将活动增量添加到现有数据库?
正常activity写作
Database.write()
将替换整个数据库。最好的方法是在 python 中创建数据库,然后写入整个内容:
data = {}
for i in range(10):
# some code here that generates data
data['foo'] = 'bar'
Database('myDatabase').write(data)
动态生成数据集
但是,如果您要从现有数据库动态创建聚合数据集,则可以在自定义生成器中创建单独的数据集。此生成器需要支持以下内容:
__iter__
: Returns 数据库键。用于检查每个数据集是否属于正在写入的数据库。因此我们只需要return第一个元素。
__len__
: 要写入的数据集数。
keys
:用于给mapping
. 添加key
values
:用于将 activity 个位置添加到 geomapping
。由于我们的源数据库和聚合系统数据库中的位置相同,我们可以在此处提供原始数据集。
items
:新键和数据集。
代码如下:
class IterativeSystemGenerator(object):
def __init__(self, from_db_name, to_db_name):
self.source = Database(from_db_name)
self.new_name = to_db_name
self.lca = LCA({self.source.random(): 1})
self.lca.lci(factorize=True)
def __len__(self):
return len(self.source)
def __iter__(self):
yield ((self.new_name,))
def get_exchanges(self):
vector = self.lca.inventory.sum(axis=1)
assert vector.shape == (len(self.lca.biosphere_dict), 1)
return [{
'input': flow,
'amount': float(vector[index]),
'type': 'biosphere',
} for flow, index in self.lca.biosphere_dict.items()
if abs(float(vector[index])) > 1e-17]
def keys(self):
for act in self.source:
yield (self.new_name, act['code'])
def values(self):
for act in self.source:
yield act
def items(self):
for act in self.source:
self.lca.redo_lci({act: 1})
obj = copy.deepcopy(act._data)
obj['database'] = self.new_name
obj['exchanges'] = self.get_exchanges()
yield ((self.new_name, obj['code']), obj)
和用法:
new_name = "ecoinvent 3.2 cutoff aggregated"
new_data = IterativeSystemGenerator("ecoinvent 3.2 cutoff", new_name)
Database(new_name).write(new_data)
这种方法的局限性
如果您正在编写如此多的数据集或数据集内的交换,以至于您 运行 陷入内存问题,那么您也可能使用了错误的工具。当前的数据库表和矩阵构建器系统使用稀疏矩阵。在这种情况下,密集矩阵会更有意义。例如,IO table backend skips the database entirely, and just writes processed arrays。如果生物圈矩阵有 13.000 * 1.500 = 20.000.000 个条目,则加载和创建生物圈矩阵需要很长时间。在这种特定情况下,我的第一直觉是尝试以下操作之一:
- 不要将生物圈流量写入数据库,而是按聚合过程单独保存,然后在清单计算后添加。
- 为每个聚合系统进程创建一个单独的数据库。
我有一个生成数据并将其写入数据库的循环:
myDatabase = Database('myDatabase')
for i in range(10):
#some code here that generates dictionaries that can be saved as activities
myDatabase.write({('myDatabase', 'valid code'): activityDict})
这样创建的单个活动可以保存到数据库中。但是,当创建多个时,数据库的长度始终为 1,只有最后一个 activity 进入数据库。
因为我有很多非常大的数据集,所以将它们全部存储在一个字典中并一次写入数据库并不方便。
有没有办法将活动增量添加到现有数据库?
正常activity写作
Database.write()
将替换整个数据库。最好的方法是在 python 中创建数据库,然后写入整个内容:
data = {}
for i in range(10):
# some code here that generates data
data['foo'] = 'bar'
Database('myDatabase').write(data)
动态生成数据集
但是,如果您要从现有数据库动态创建聚合数据集,则可以在自定义生成器中创建单独的数据集。此生成器需要支持以下内容:
__iter__
: Returns 数据库键。用于检查每个数据集是否属于正在写入的数据库。因此我们只需要return第一个元素。__len__
: 要写入的数据集数。keys
:用于给mapping
. 添加key
values
:用于将 activity 个位置添加到geomapping
。由于我们的源数据库和聚合系统数据库中的位置相同,我们可以在此处提供原始数据集。items
:新键和数据集。
代码如下:
class IterativeSystemGenerator(object):
def __init__(self, from_db_name, to_db_name):
self.source = Database(from_db_name)
self.new_name = to_db_name
self.lca = LCA({self.source.random(): 1})
self.lca.lci(factorize=True)
def __len__(self):
return len(self.source)
def __iter__(self):
yield ((self.new_name,))
def get_exchanges(self):
vector = self.lca.inventory.sum(axis=1)
assert vector.shape == (len(self.lca.biosphere_dict), 1)
return [{
'input': flow,
'amount': float(vector[index]),
'type': 'biosphere',
} for flow, index in self.lca.biosphere_dict.items()
if abs(float(vector[index])) > 1e-17]
def keys(self):
for act in self.source:
yield (self.new_name, act['code'])
def values(self):
for act in self.source:
yield act
def items(self):
for act in self.source:
self.lca.redo_lci({act: 1})
obj = copy.deepcopy(act._data)
obj['database'] = self.new_name
obj['exchanges'] = self.get_exchanges()
yield ((self.new_name, obj['code']), obj)
和用法:
new_name = "ecoinvent 3.2 cutoff aggregated"
new_data = IterativeSystemGenerator("ecoinvent 3.2 cutoff", new_name)
Database(new_name).write(new_data)
这种方法的局限性
如果您正在编写如此多的数据集或数据集内的交换,以至于您 运行 陷入内存问题,那么您也可能使用了错误的工具。当前的数据库表和矩阵构建器系统使用稀疏矩阵。在这种情况下,密集矩阵会更有意义。例如,IO table backend skips the database entirely, and just writes processed arrays。如果生物圈矩阵有 13.000 * 1.500 = 20.000.000 个条目,则加载和创建生物圈矩阵需要很长时间。在这种特定情况下,我的第一直觉是尝试以下操作之一:
- 不要将生物圈流量写入数据库,而是按聚合过程单独保存,然后在清单计算后添加。
- 为每个聚合系统进程创建一个单独的数据库。