def cumulative(x, first_year, last_year):
    """Returns the cumulative sum of a timeseries (indexed over years),
    implements linear interpolation between years, ignores nan's in the range.
    The function includes the last-year value of the series, and
    raises a warning if start_year or last_year is outside of
    the timeseries range and returns nan

    Parameters
    ----------
    x: pandas.Series
        a timeseries to be summed over time
    first_year: int
        first year of the sum
    last_year: int
        last year of the sum (inclusive)
    """
    # if the timeseries does not cover the range `[first_year, last_year]`,
    # return nan to avoid erroneous aggregation
    if min(x.index) > first_year:
        logger().warning('the timeseries `{}` does not start by {}'.format(
            x.name or x, first_year))
        return np.nan
    if max(x.index) < last_year:
        logger().warning('the timeseries `{}` does not extend until {}'
                         .format(x.name or x, last_year))
        return np.nan

    # make sure we're using integers
    to_int(x, index=True)

    x[first_year] = fill_series(x, first_year)
    x[last_year] = fill_series(x, last_year)

    years = [i for i in x.index if i >= first_year and i <= last_year
             and ~np.isnan(x[i])]
    years.sort()

    # loop over years
    if not np.isnan(x[first_year]) and not np.isnan(x[last_year]):
        value = 0
        for (i, yr) in enumerate(years[:-1]):
            next_yr = years[i + 1]
            # the summation is shifted to include the first year fully in sum,
            # otherwise, would return a weighted average of `yr` and `next_yr`
            value += ((next_yr - yr - 1) * x[next_yr] +
                      (next_yr - yr + 1) * x[yr]) / 2

        # the loop above does not include the last element in range
        # (`last_year`), therefore added explicitly
        value += x[last_year]

        return value
def cumulative ( x , first_year , last_year ) : if min ( x . index ) > first_year : logger ( ) . warning ( 'the timeseries `{}` does not start by {}' . format ( x . name or x , first_year ) ) return np . nan if max ( x . index ) < last_year : logger ( ) . warning ( 'the timeseries `{}` does not extend until {}' . format ( x . name or x , last_year ) ) return np . nan to_int ( x , index = True ) x [ first_year ] = fill_series ( x , first_year ) x [ last_year ] = fill_series ( x , last_year ) years = [ i for i in x . index if i >= first_year and i <= last_year and ~ np . isnan ( x [ i ] ) ] years . sort ( ) if not np . isnan ( x [ first_year ] ) and not np . isnan ( x [ last_year ] ) : value = 0 for ( i , yr ) in enumerate ( years [ : - 1 ] ) : next_yr = years [ i + 1 ] value += ( ( next_yr - yr - 1 ) * x [ next_yr ] + ( next_yr - yr + 1 ) * x [ yr ] ) / 2 value += x [ last_year ] return value
Returns the cumulative sum of a timeseries (indexed over years),
    implements linear interpolation between years, ignores nan's in the range.
    The function includes the last-year value of the series, and
    raises a warning if start_year or last_year is outside of
    the timeseries range and returns nan

    Parameters
    ----------
    x: pandas.Series
        a timeseries to be summed over time
    first_year: int
        first year of the sum
    last_year: int
        last year of the sum (inclusive)