nomenclature icon indicating copy to clipboard operation
nomenclature copied to clipboard

Get countries in common-regions

Open danielhuppmann opened this issue 1 year ago • 3 comments

@laurinks asked me about a model-specific common-region-to-country mapping, so I whipped together this code. Maybe useful going forward

dsd = nomenclature.DataStructureDefinition("definitions/")
rp = nomenclature.RegionProcessor.from_directory("mappings/", dsd)

def get_model_country_mapping(model):
    model_mapping = rp.mappings[model]
    
    model_country_mapping = dict()
    for common_region in model_mapping.common_regions:
        _list = list()
        for constituent_region in common_region.constituent_regions:
            _list.extend(dsd.region[model_mapping.rename_mapping[constituent_region]].countries)
        model_country_mapping[common_region.name] = _list

    return model_mapping

fyi @phackstock @SferraFab @dc-almeida

danielhuppmann avatar Oct 01 '24 05:10 danielhuppmann

Very nice, I think this should become a property of the RegionAggregationMapping class.

This way, you could run:

dsd = nomenclature.DataStructureDefinition("definitions/")
rp = nomenclature.RegionProcessor.from_directory("mappings/", dsd)
model="Some Model"

rp.mappings[model].common_region_country_mapping

and would get the desired mapping. In addition you could also add RegionAggregationMapping.native_region_country_mapping.

Or something along those lines with a less verbose name.

phackstock avatar Oct 01 '24 06:10 phackstock

Might be easier to add it as a property of the CommonRegion class (which is implicltly model-dependent). https://github.com/IAMconsortium/nomenclature/blob/30fb5b14d34da4c8905f54df4d16f2a38a24abc3/nomenclature/processor/region.py#L64

And adding a "getter" would also be helpful, currently there are only lists.

rp.mappings[model].get["Asia (R5)"].countries

danielhuppmann avatar Oct 01 '24 08:10 danielhuppmann

@danielhuppmann Thanks a lot. It is indeed very useful.

Based on the suggested function above (but returning model_country_mapping instead of model_mapping - I guess this was a typo), I am extracting Excel tables for each common region (R5 or R10) which contain information on the countries included in the region for each model (see attached files).

Maybe useful also for other teams when doing multi-model analysis on R10 or R5 levels. (I am not familiar with the nomenclature, so the code can certainly be improved.)

#List of models: As IMAGE complained about IND, I commented out the mapping for G20 members in common-definitions/mappings/IMAGE_v3.4.yaml
scenarioMIP_models = ["AIM 3.0", "COFFEE 1.5", "GCAM 7.1 scenarioMIP", "IMAGE 3.4", "MESSAGEix-GLOBIOM 2.1-M-R12", "REMIND-MAgPIE 3.4-4.8","WITCH 6.0"] 
#List of common regions
common_regions = ["OECD & EU (R5)", "Reforming Economies (R5)", "Asia (R5)", "Middle East & Africa (R5)", "Latin America (R5)"]
# common_regions = ["Africa (R10)","Rest of Asia (R10)","Reforming Economies (R10)","Pacific OECD (R10)","North America (R10)","Middle East (R10)","Latin America (R10)","India+ (R10)","Europe (R10)","China+ (R10)"]

# List of all countries
all_countries = list()
for region in common_regions:
    all_countries = all_countries + dsd.region[region].countries

# Function returning dataframe with -1/0/1 entries indicating if countries (rows) are incorrectly/not/correctly contained in region for models (columns)
def get_model_region_country_mapping(region):
    model_region_country_mapping = dict()
    # Add common region definition
    model_region_country_mapping["Definition"] = dsd.region[region].countries
    # Add model region definition
    for model in scenarioMIP_models:
        model_region_country_mapping[model] = get_model_country_mapping(model)[region]

    # Initialize dataframe
    df = pandas.DataFrame(index = all_countries, columns=model_region_country_mapping.keys())

    # Add true/false to column Definition 
    # Add 1 if country correctly included, add -1 if country incorrectly included, add 0 if country not included
    for model, country_list in model_region_country_mapping.items():
        if model == "Definition":
            df[model] = df.index.isin(country_list).astype(bool)
        else:
            df[model] = df.index.isin(country_list).astype(int)
    
    df.iloc[:, 1:] = df.apply(lambda row: row[1:] * (1 if row['Definition'] else -1), axis=1)
    
    
    df["TOTAL"] = df.drop(columns=["Definition"]).sum(axis=1)
    df = df = df[(df["TOTAL"] != 0) | (df["Definition"] == True)]
    df = df.sort_values(by="TOTAL", ascending=False)

    return df


output_file = 'R5_model_comparison.xlsx'
# output_file = 'R10_model_comparison.xlsx'
with pandas.ExcelWriter(output_file, engine='openpyxl') as writer:
    for region in common_regions:
        df = get_model_region_country_mapping(region)
        df.to_excel(writer, sheet_name=region, index=True)

R10_model_comparison.xlsx R5_model_comparison.xlsx

laurinks avatar Oct 25 '24 15:10 laurinks