<commit_before>"""
Routines for geographically re-sampling regional electricity demand.

Electricity demand is reported by a variety of entities, pertaining to many
different geographic areas. It's often useful to be able to estimate how
demand reported for one geography maps onto another. For instance, taking the
total hourly electricity demand reported with in an ISO region or utility
planning area, and allocating it to individual counties according to their
populations, as reported within US Census tracts.

This process involves 3 different kinds of geometries:

* The demand source geometry, i.e. area associated with the reported demand
* One or more geometries having data associated with them that will be used
  to inform the geographic allocation of the reported demand. E.g. US
  census tract boundaries and their reported populations.
* The output or target geometry, to which the geographically allocated demand
  will be aggregated for final use. E.g. counties, states, NREL ReEDS
  balancing areas, or EPA's IPM regions.

First we calculate the intersection of the reporting demand areas and the
geometires which have data we want to use to allocate demand geographically.

Second, for each of those intersecting areas, we use data associated with the
non-demand geometry to calculate a weighting factor that will determine what
share of the overall demand that area gets.

Third, we use these weights and the demand time series keyed to the IDs of the
demand areas to generate new demand time series for each of the intersecting
geometries.

Finally, we aggregate the demand that has been allocated to the intersecting
areas up to the areas identified within the target output geometry.

"""
import geopandas
import pandas as pd


def create_stacked_intersection_df(gdf_primary, gdf_secondary, gdf_primary_col="FIPS",
                                   gdf_secondary_col="ID", geom_primary="geometry",
                                   geom_secondary="geometry"):
    """
    Builds matrix with 1-1 mapping of primary and secondary dataframe.

    Returns a stacked dataframe with all the fraction of intersecting areas
    for both geometries. The CRS for both of the geodataframes should be the
    same.

    Inputs:

        gdf_primary (GeoDataframe): primaryer geodataframe
        gdf_secondary (GeoDataframe): secondaryr dataframe
        gdf_primary_col (str): index column for gdf_primary
        gdf_secondary_col(str): index column for gdf_secondary
        file_save (bool): save file option

    Outputs:

        returns new_df: dataframe with columns primary_index, secondary_index,
                primary_intersection_fraction, secondary_intersection_fraction

    """
    new_df = geopandas.overlay(gdf_primary[[gdf_primary_col, geom_primary]], gdf_secondary[[
                               gdf_secondary_col, geom_secondary]], how='intersection')
    new_df["area_derived"] = new_df["geometry"].area

    gdf_primary["primary_area_derived"] = gdf_primary[geom_primary].area
    gdf_secondary["secondary_area_derived"] = gdf_secondary[geom_secondary].area

    new_df = (new_df[[gdf_primary_col, gdf_secondary_col, "geometry"]]
              .merge(gdf_primary[[gdf_primary_col, "primary_area_derived"]])
              .merge(gdf_secondary[[gdf_secondary_col, "secondary_area_derived"]]))

    new_df["gdf_primary_intersection_fraction"] = new_df["area_derived"] / \
        new_df["primary_area_derived"]
    new_df["gdf_secondary_intersection_fraction"] = new_df["area_derived"] / \
        new_df["secondary_area_derived"]

    new_df = new_df[[gdf_primary_col, gdf_secondary_col, "gdf_primary_intersection_fraction",
                     "gdf_secondary_intersection_fraction"]]

    return new_df


def create_intersection_matrix(gdf_intersection, gdf_intersection_col="gdf_primary_intersection_fraction",
                               gdf_primary_col="FIPS", gdf_secondary_col="ID", normalization=True, normalize_axis=1):
    """
    Converts stacked dataframe to an intersection matrix.

    Provides the intersection matrix with the area intersection fraction a[i, j] for every primary id i
    and secondary id j. Normalization option available (To normalize double-counting)

    Inputs:<commit_msg>Modified bug in create_stacked_intersection_df Function<commit_after>"""
Routines for geographically re-sampling regional electricity demand.

Electricity demand is reported by a variety of entities, pertaining to many
different geographic areas. It's often useful to be able to estimate how
demand reported for one geography maps onto another. For instance, taking the
total hourly electricity demand reported with in an ISO region or utility
planning area, and allocating it to individual counties according to their
populations, as reported within US Census tracts.

This process involves 3 different kinds of geometries:

* The demand source geometry, i.e. area associated with the reported demand
* One or more geometries having data associated with them that will be used
  to inform the geographic allocation of the reported demand. E.g. US
  census tract boundaries and their reported populations.
* The output or target geometry, to which the geographically allocated demand
  will be aggregated for final use. E.g. counties, states, NREL ReEDS
  balancing areas, or EPA's IPM regions.

First we calculate the intersection of the reporting demand areas and the
geometires which have data we want to use to allocate demand geographically.

Second, for each of those intersecting areas, we use data associated with the
non-demand geometry to calculate a weighting factor that will determine what
share of the overall demand that area gets.

Third, we use these weights and the demand time series keyed to the IDs of the
demand areas to generate new demand time series for each of the intersecting
geometries.

Finally, we aggregate the demand that has been allocated to the intersecting
areas up to the areas identified within the target output geometry.

"""
import geopandas
import pandas as pd


def create_stacked_intersection_df(gdf_primary, gdf_secondary, gdf_primary_col="FIPS",
                                   gdf_secondary_col="ID", geom_primary="geometry",
                                   geom_secondary="geometry"):
    """
    Builds matrix with 1-1 mapping of primary and secondary dataframe.

    Returns a stacked dataframe with all the fraction of intersecting areas
    for both geometries. The CRS for both of the geodataframes should be the
    same.

    Inputs:

        gdf_primary (GeoDataframe): primaryer geodataframe
        gdf_secondary (GeoDataframe): secondaryr dataframe
        gdf_primary_col (str): index column for gdf_primary
        gdf_secondary_col(str): index column for gdf_secondary
        file_save (bool): save file option

    Outputs:

        returns new_df: dataframe with columns primary_index, secondary_index,
                primary_intersection_fraction, secondary_intersection_fraction

    """
    new_df = geopandas.overlay(gdf_primary[[gdf_primary_col, geom_primary]], gdf_secondary[[
                               gdf_secondary_col, geom_secondary]], how='intersection')
    new_df["area_derived"] = new_df["geometry"].area

    gdf_primary["primary_area_derived"] = gdf_primary[geom_primary].area
    gdf_secondary["secondary_area_derived"] = gdf_secondary[geom_secondary].area

    new_df = (new_df[[gdf_primary_col, gdf_secondary_col, "area_derived", "geometry"]]
              .merge(gdf_primary[[gdf_primary_col, "primary_area_derived"]])
              .merge(gdf_secondary[[gdf_secondary_col, "secondary_area_derived"]]))

    new_df["gdf_primary_intersection_fraction"] = new_df["area_derived"] / \
        new_df["primary_area_derived"]
    new_df["gdf_secondary_intersection_fraction"] = new_df["area_derived"] / \
        new_df["secondary_area_derived"]

    new_df = new_df[[gdf_primary_col, gdf_secondary_col, "gdf_primary_intersection_fraction",
                     "gdf_secondary_intersection_fraction"]]

    return new_df


def create_intersection_matrix(gdf_intersection, gdf_intersection_col="gdf_primary_intersection_fraction",
                               gdf_primary_col="FIPS", gdf_secondary_col="ID", normalization=True, normalize_axis=1):
    """
    Converts stacked dataframe to an intersection matrix.

    Provides the intersection matrix with the area intersection fraction a[i, j] for every primary id i
    and secondary id j. Normalization option available (To normalize double-counting)

    Inputs:
{'fraction_non_alphanumeric': 0.058294392523364484, 'fraction_numerical': 0.0009345794392523365, 'mean_word_length': 3.9831199068684517, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1194677', 'n_tokens_mistral': 2373, 'n_tokens_neox': 2211, 'n_words': 842}