Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add API to change a time axis frequency #1119

Open
gdementen opened this issue Oct 17, 2024 · 1 comment
Open

add API to change a time axis frequency #1119

gdementen opened this issue Oct 17, 2024 · 1 comment

Comments

@gdementen
Copy link
Contributor

Yesterday I created the following function (for vs):

def monthly_to_quarterly(axis_or_group, first_year=None, last_year=None):
    """
    Produces a tuple of groups to aggregate an array with a monthly axis to a quarterly axis
    
    The monthly axis must have labels using the "{YYYY}M{M}" format
    (M goes from 1 to 12, not 01 to 12).
    The quarterly axis will have labels using the "{YYYY}Q{Q}" format.
    
    Parameters
    ----------
    axis_or_group : Axis or Group
        Original monthly axis (or selection on it).
    first_year : int, optional
        First year taken into account. Defaults to the first year present on the axis.
    last_year : int, optional
        Last year taken into account. Defaults to the last year present on the axis.        

    Returns
    -------
    tuple
        Groups which can be used to aggregate an array with the original monthly axis
        into a quarterly axis

    Examples
    --------
    >>> time = Axis(f"2024M3..2024M10", 'time')
    >>> arr = ndtest(time)
    >>> arr
    time  2024M3  2024M4  2024M5  2024M6  2024M7  2024M8  2024M9  2024M10
               0       1       2       3       4       5       6        7    
    >>> quarter_months = monthly_to_quarterly(time)
    >>> quarter_months
    (time['2024M3'] >> '2024Q1',
     time['2024M4', '2024M5', '2024M6'] >> '2024Q2',
     time['2024M7', '2024M8', '2024M9'] >> '2024Q3',
     time['2024M10'] >> '2024Q4')
    >>> arr.sum(quarter_months)
    time  2024Q1  2024Q2  2024Q3  2024Q4
               0       6      15       7
    """
    labels = axis_or_group.labels if isinstance(axis_or_group, Axis) else axis_or_group.eval()
    axis = axis_or_group if isinstance(axis_or_group, Axis) else axis_or_group.axis
    group = axis[:] if isinstance(axis_or_group, Axis) else axis_or_group
    if first_year is None or last_year is None:
        years = set(int(label[:4]) for label in labels)
        if first_year is None:
            first_year = min(years)
        if last_year is None:
            last_year = max(years)
    quarters = []
    for y in range(first_year, last_year + 1):
        for q in range(1, 5):
            quarter_months = f"{y}M{(q - 1) * 3 + 1}..{y}M{(q - 1) * 3 + 3}"
            # support axes/selections which do not start at the first month
            quarter_months_in_selection = group.intersection(quarter_months)

            # avoid "empty" quarters, if the axis has no month for some quarters
            if quarter_months_in_selection:
                # transform the LSet returned by .intersection() to a normal LGroup
                # this step is not strictly necessary but produces nicer groups            
                quarter_months_in_selection = axis[quarter_months_in_selection.eval()]
                quarters.append(quarter_months_in_selection >> f'{y}Q{q}')
    return tuple(quarters)

I think we should generalize this further and add something which can do this kind of conversion in LArray.

A few references:

@gdementen
Copy link
Contributor Author

gdementen commented Nov 20, 2024

FWIW, yesterday, I made the similar function quarterly_to_yearly (for vs again). This one simplifies to:

def quarterly_to_yearly(axis_or_group):
    """
    Produces a tuple of groups to aggregate an array with a quarterly axis to a 
    yearly (integer) axis

    The quarterly axis must have labels using the "{YYYY}Q{Q}" format
    (Q goes from 1 to 4).

    Parameters
    ----------
    axis_or_group : Axis or Group
        Original quarterly axis (or selection on it).

    Returns
    -------
    tuple
        Groups which can be used to aggregate an array with the original 
        quarterly axis into a yearly (integer) axis

    Examples
    --------
    >>> time = Axis(f"2023Q2..2023Q4,2024Q1..2024Q3", 'time')
    >>> arr = ndtest(time)
    >>> arr
    time  2023Q2  2023Q3  2023Q4  2024Q1  2024Q2  2024Q3
               0       1       2       3       4       5    
    >>> year_quarters = quarterly_to_yearly(time)
    >>> year_quarters
    (time['2023Q2', '2023Q3', '2023Q4'] >> 2023,
     time['2024Q1', '2024Q2', '2024Q3'] >> 2024)
    >>> arr.sum(year_quarters)
    time  2023  2024
             3    12
    """
    labels = axis_or_group.labels if isinstance(axis_or_group, Axis) else axis_or_group.eval()
    years = sorted(set([int(label[:4]) for label in labels]))
    return tuple([axis_or_group.startingwith(str(y)) >> y
                  for y in years])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant