Search code examples
brightway

unable to use bw2calc.LCA.to_dafaframe to export LCI data


I am trying to use LCA.to_dataframe to export LCI for specific activites. Previously I used the matrix_label and cutoff parameters; however, this doesn't seem to work for me anymore, and I am wondering if I am not using it correctly.

The code that I've tried (bw2calc version is (1.8.2)

import bw2calc as bc
import bw2data as bd

ptint(bc.__version__)
eidb = bd.Database("ecoinvent 3.5 cutoff")

# random activity
random_act = eidb.random()
funct_unit = {random_act:1}

# lca, lci
lca = bc.LCA(funct_unit, ('IPCC 2021', 'climate change', 'global warming potential (GWP100)'))
lca.lci()
lca.lcia()
lca.to_dataframe(matrix_label = "inventory", cutoff = None)

The error message was:

LCA.to_dataframe() got an unexpected keyword argument 'matrix_label'

Is there a way to get the inventory dataframe besides calling lca.inventory and convert the inventory matrix to dataframe myself?

Thanks in advance!


Solution

  • Brightway2 doesn't support matrix_label, this is a new feature added in 2.5. But we can pretty easily write a function to generate a DataFrame in the form you want:

    import bw2data as bd
    import pandas as pd
    import numpy as np
    from scipy.sparse import spmatrix
    from typing import Callable, Optional
    from numbers import Number
    
    
    def to_dataframe(
            matrix: spmatrix, 
            reverse_row: dict, 
            reverse_col: dict, 
            obj_lookup: Callable = lambda x: bd.get_activity(x), 
            cutoff: Optional[Number] = 0.01,
            fields: list[str] = ['name', 'location', 'unit']
        ):
        matrix = matrix.tocoo()
        elements = np.vstack([matrix.data, matrix.row, matrix.col]).T
        order = np.argsort(np.abs(matrix.data))[::-1]
        elements = elements[order, :]
        
        if cutoff:
            assert cutoff > 0 and cutoff < 1
            cutoff_value = cutoff * matrix.sum()
            mask = elements[:, 0] >= cutoff_value
            elements = elements[mask, :]
        
        row_lookup, col_lookup = {}, {}
        data = []
        
        for amount, row, col in elements:
            if row not in row_lookup:
                row_lookup[row] = obj_lookup(reverse_row[row])
            if col not in col_lookup:
                col_lookup[col] = obj_lookup(reverse_col[col])
    
            row_obj, col_obj = row_lookup[row], col_lookup[col]
                
            obj = {'amount': amount}
            for field in fields:
                obj[f"row_{field}"] = row_obj.get(field)
                obj[f"col_{field}"] = col_obj.get(field)
            data.append(obj)
                
        return pd.DataFrame(data)
    

    I hope this is self-explanatory. Here is an example of it in action:

    import bw2data as bd
    import bw2calc as bc
    
    bd.projects.set_current("ecoinvent-3.8-cutoff")    
    
    ei = bd.Database("ecoinvent-3.8-cutoff")
    fu = {ei.random(): 1}
    ipcc = ('IPCC 2013', 'climate change', 'GWP 100a')
    lca = bc.LCA(fu, ipcc)
    lca.lci()
    lca.lcia()
    reverse_col, _, reverse_row = lca.reverse_dict()
    to_dataframe(lca.inventory, reverse_row, reverse_col)