brightway-lca / brightway2-io

Importing and exporting for the Brightway LCA framework
BSD 3-Clause "New" or "Revised" License
26 stars 40 forks source link

`ExcelImporter` should convert integer codes to strings #259

Closed danielPclos closed 2 months ago

danielPclos commented 2 months ago

Hi,

I'm trying to load an inventory using the ExcelImporter class having first successfully executed the apply_strategies(), match_database() (with 0 unlinked exchanges) and statistics() methods.

When executing the write_database() method, all activities from the inventory seem to be successfully loaded (from activity-browser inspection) but in the end it throws a KeyError which reads: ("name_of_database_being_loaded", "code_of_one_of_the_loaded_activities").

If I delete said activity from the excel file, the error persists with another of the succesfully loaded activities.

Finally, if I try to perform a minimalistic LCA calculation on this inventory I get a FileNotFoundError: C:\Users\xxx\AppData\Local\pylca\Brightway3\project_id\processed\database_id.npy

which I suspect should have been created by write_database() method but failed to do so due to the error described above.

I attach the excel template we are using with only the first 2 activities as reference.

Thanks in advanced for any help in solving this issue! :)

lci_bw_minim.xlsx

cmutel commented 2 months ago

The ExcelImporter is incorrectly reading the code value as an integer:

>>> import bw2io as bi
>>> excel = bi.ExcelImporter("lci_bw_minim.xlsx")
>>> excel.apply_strategies()
>>> excel.data[0]['code']
41000000
>>> type(excel.data[0]['code'])
int

I don't know how this breaks stuff, but it is definitely the problem. Luckily it is easy to fix:

def codes_as_strings(data):
    for ds in data:
        ds['code'] = str(ds['code'])
    return data

excel.apply_strategy(codes_as_strings)

BTW, to import the sample database I had to relabel the "product" column:

def relabel_products(data):
    for ds in data:
        for exc in ds['exchanges']:
            exc['reference product'] = exc['product']
    return data

excel.apply_strategy(relabel_products)

I can then do LCA calculations and get LCIA scores.

danielPclos commented 2 months ago

Dear Christopher,

Thank you so much for your quick response. Your solution works fine! 🙂

Kind regards, Daniel

danielPclos commented 2 months ago

Hi again,

Just a small edit to the answer. To make it work on my side I needed to send the code_as_strings as a list since apply_strategies expects such argument type:

excel.apply_strategy([codes_as_strings])

cmutel commented 2 months ago

@danielPclos apply_strategy takes a single function, apply_strategies takes a list of functions. In you last comment you used both terms :)

danielPclos commented 2 months ago

Thanks @cmutel, I'm a bit blind so now I understand why was I getting inconsistent behavior due to interchange of these 2 methods. :)