WeightedLowess
A C++ library for LOWESS with various weighting schemes
Loading...
Searching...
No Matches
WeightedLowess Namespace Reference

Namespace for LOWESS functions. More...

Classes

struct  AssignedSegments
 Assigned segments. More...
 
struct  Options
 Options for compute(). More...
 
struct  PrecomputedWindows
 Precomputed windows for LOWESS smoothing. More...
 
struct  Results
 Results of the LOWESS smoother. More...
 
class  SortBy
 Utility class for sorting on a covariate. More...
 

Functions

template<typename Data_ >
void compute (const std::size_t num_points, const Data_ *const x, const PrecomputedWindows< Data_ > &windows, const Data_ *const y, Data_ *const fitted, Data_ *robust_weights, const Options< Data_ > &opt)
 
template<typename Data_ >
void compute (const std::size_t num_points, const Data_ *const x, const Data_ *const y, Data_ *const fitted, Data_ *const robust_weights, const Options< Data_ > &opt)
 
template<typename Data_ >
Results< Data_ > compute (const std::size_t num_points, const Data_ *const x, const Data_ *const y, const Options< Data_ > &opt)
 
template<typename Data_ >
AssignedSegments assign_to_segments (const Data_ *const x_fit, const PrecomputedWindows< Data_ > &windows_fit, const std::size_t num_points_out, const Data_ *const x_out)
 
std::pair< std::size_t, std::size_t > get_interpolation_boundaries (const AssignedSegments &assigned_out)
 
template<typename Data_ >
void interpolate (const Data_ *const x_fit, const PrecomputedWindows< Data_ > &windows_fit, const Data_ *const fitted_fit, const Data_ *const x_out, const AssignedSegments &assigned_out, Data_ *const fitted_out, int num_threads)
 
template<typename Data_ >
std::pair< std::size_t, std::size_t > interpolate (const Data_ *const x_fit, const PrecomputedWindows< Data_ > &windows_fit, const Data_ *const fitted_fit, const std::size_t num_points_out, const Data_ *const x_out, Data_ *const fitted_out, int num_threads)
 
template<typename Task_ , class Run_ >
void parallelize (const int num_workers, const Task_ num_tasks, Run_ run_task_range)
 
template<typename Data_ >
PrecomputedWindows< Data_ > define_windows (const std::size_t num_points, const Data_ *const x, const Options< Data_ > &opt)
 

Detailed Description

Namespace for LOWESS functions.

Function Documentation

◆ assign_to_segments()

template<typename Data_ >
AssignedSegments WeightedLowess::assign_to_segments ( const Data_ *const x_fit,
const PrecomputedWindows< Data_ > & windows_fit,
const std::size_t num_points_out,
const Data_ *const x_out )

Assign points-to-be-interpolated to their corresponding segments between anchors, for use in interpolate(). Segments are defined as the line between two adjacent anchors, to be used for linear interpolation of any intervening points.

Template Parameters
Data_Floating-point type of the data.
Parameters
[in]x_fitPointer to an array of x-coordinates for the fitted trend from compute(). This should be sorted in increasing order.
windows_fitPrecomputed windows for anchor points, created by calling define_windows() on x_fit.
num_points_outNumber of points to be interpolated.
[in]x_outPointer to an array of x-coordinates of the points to be interpolated. This should be sorted in increasing order and have length equal to num_points_out.
Returns
Assignment of each point in x_out to its corresponding segment, where possible. This can be re-used for multiple interpolate() calls with different fitted values.

◆ compute() [1/3]

template<typename Data_ >
Results< Data_ > WeightedLowess::compute ( const std::size_t num_points,
const Data_ *const x,
const Data_ *const y,
const Options< Data_ > & opt )

Overload of compute() that allocates storage for the results of the smoothing.

Template Parameters
Data_Floating-point type of the data.
Parameters
num_pointsNumber of points.
[in]xPointer to an array of num_points x-coordinates, sorted in increasing order. (Consider using SortBy to permute x in-place. Note that the same permutation should be applied to y and, if present, weights in Options::weights.)
[in]yPointer to an array of num_points y-coordinates.
optFurther options.
Returns
A Results object containing the fitted values and robustness weights.

◆ compute() [2/3]

template<typename Data_ >
void WeightedLowess::compute ( const std::size_t num_points,
const Data_ *const x,
const Data_ *const y,
Data_ *const fitted,
Data_ *const robust_weights,
const Options< Data_ > & opt )

Overload of compute() that computes the windows around each anchor point.

Template Parameters
Data_Floating-point type of the data.
Parameters
num_pointsNumber of points.
[in]xPointer to an array of num_points x-coordinates, sorted in increasing order. (Consider using SortBy to permute x in-place. Note that the same permutation should be applied to y and, if present, weights in Options::weights.)
[in]yPointer to an array of num_points y-coordinates.
[out]fittedPointer to an output array of length num_points, in which the fitted values of the smoother can be stored.
[out]robust_weightsPointer to an output array of length num_points, in which the robustness weights can be stored. This may be NULL if the robustness weights are not needed.
optFurther options.

◆ compute() [3/3]

template<typename Data_ >
void WeightedLowess::compute ( const std::size_t num_points,
const Data_ *const x,
const PrecomputedWindows< Data_ > & windows,
const Data_ *const y,
Data_ *const fitted,
Data_ * robust_weights,
const Options< Data_ > & opt )

Run the LOWESS algorithm for non-parametric smoothing.

First, we identify anchor points that have (roughly) evenly-spaced x-coordinates. For each anchor point, we identify a window of neighboring points and compute a weight for each neighbor based on its distance to the anchor. We perform a weighted linear regression to obtain a fitted value for the anchor. For all non-anchor points, we compute a fitted value via linear interpolation of the surrounding anchor points. We then compute robustness weights for each point based on their deviation from the fitted value; the regressions are then repeated with robustness weights for the specified number of iterations.

Template Parameters
Data_Floating-point type of the data.
Parameters
num_pointsNumber of points.
[in]xPointer to an array of num_points x-coordinates, sorted in increasing order. (Consider using SortBy to permute x in-place. Note that the same permutation should be applied to y and, if present, weights in Options::weights.)
windowsPrecomputed windows around the anchor points, created by calling define_windows() with num_points, x and opt. This can be re-used across multiple calls to compute() with different y.
[in]yPointer to an array of num_points y-coordinates.
[out]fittedPointer to an output array of length num_points, in which the fitted values of the smoother can be stored.
[out]robust_weightsPointer to an output array of length num_points, in which the robustness weights can be stored. This may be NULL if the robustness weights are not needed.
optFurther options. This should be the same object that is used in define_windows(). Note that only a subset of options are actually used in this overload, namely Options::weights and Options::iterations.

◆ define_windows()

template<typename Data_ >
PrecomputedWindows< Data_ > WeightedLowess::define_windows ( const std::size_t num_points,
const Data_ *const x,
const Options< Data_ > & opt )

Identify anchor points and precompute the associated windows prior to LOWESS smoothing via compute(). This avoids wasting time in unnecessarily recomputing the same windows for the same x but different y in multiple compute() calls.

Template Parameters
Data_Floating-point type of the data.
Parameters
num_pointsNumber of points.
[in]xPointer to an array of num_points x-coordinates, sorted in increasing order. (Consider using SortBy to permute the array in-place before calling this function.)
optFurther options. Only a subset of options are actually used here, namely Options::delta, Options::anchors, Options::weights, Options::frequency_weights, Options::span, Options::span_as_proportion, and Options::minimum_width.

◆ get_interpolation_boundaries()

std::pair< std::size_t, std::size_t > WeightedLowess::get_interpolation_boundaries ( const AssignedSegments & assigned_out)
inline
Parameters
assigned_outAssignment of each point-to-be-interpolated to a inter-anchor segment, produced by assign_to_segments().
Returns
Pair containing (i) the index of the first point that lies within a segment and (ii) the index of the first point that lies beyond the final segment. This defines the subinterval of points in x_out that can be safely interpolated, i.e., do not lie beyond x_fit.

◆ interpolate() [1/2]

template<typename Data_ >
void WeightedLowess::interpolate ( const Data_ *const x_fit,
const PrecomputedWindows< Data_ > & windows_fit,
const Data_ *const fitted_fit,
const Data_ *const x_out,
const AssignedSegments & assigned_out,
Data_ *const fitted_out,
int num_threads )

Interpolate the fitted values for a set of points, based on a pre-existing trend fitted by compute().

In compute(), the LOWESS algorithm calculates fitted values exactly for anchor points and then interpolates the fitted values for all intervening points. This function applies the same interpolation to a separate set of points based only on their x-coordinates.

Template Parameters
Data_Floating-point type of the data.
Parameters
[in]x_fitPointer to an array of x-coordinates for the fitted trend from compute(). This should be sorted in increasing order.
windows_fitPrecomputed windows for anchor points, created by calling define_windows() on x_fit.
[in]fitted_fitPointer to an array of fitted values from calling compute() with x_fit and windows_fit. This should have the same length as x_fit.
[in]x_outPointer to an array of x-coordinates of the points to be interpolated. This should be sorted in increasing order.
[in]assigned_outAssignment of points-to-be-interpolated to each inter-anchor segment. This should be created by calling assign_to_segment() on x_fit, windows_fit and x_out.
[out]fitted_outPointer to an array of same length as x_out. On output, this stores the interpolated fitted value for each entry of x_out that lies within the interpolation boundaries (see get_interpolation_boundaries()). No value is stored for points that lie beyond the interpolation boundaries.
num_threadsNumber of threads to use.

◆ interpolate() [2/2]

template<typename Data_ >
std::pair< std::size_t, std::size_t > WeightedLowess::interpolate ( const Data_ *const x_fit,
const PrecomputedWindows< Data_ > & windows_fit,
const Data_ *const fitted_fit,
const std::size_t num_points_out,
const Data_ *const x_out,
Data_ *const fitted_out,
int num_threads )

Overload of interpolate() that calls assign_to_segments() automatically.

Template Parameters
Data_Floating-point type of the data.
Parameters
[in]x_fitPointer to an array of x-coordinates for the fitted trend from compute(). This should be sorted in increasing order.
windows_fitPrecomputed windows for anchor points, created by calling define_windows() on x_fit.
[in]fitted_fitPointer to an array of fitted values from calling compute() with x_fit and windows_fit. This should have the same length as x_fit.
num_points_outNumber of points to be interpolated.
[in]x_outPointer to an array of x-coordinates of the points to be interpolated. This should be sorted in increasing order.
[out]fitted_outPointer to an array of same length as x_out. On output, this stores the interpolated fitted value for each entry of x_out that lies within the interpolation boundaries. No value is stored for points that lie beyond the interpolation boundaries.
num_threadsNumber of threads to use.
Returns
Boundaries of the interpolation, see get_interpolation_boundaries() for details.

◆ parallelize()

template<typename Task_ , class Run_ >
void WeightedLowess::parallelize ( const int num_workers,
const Task_ num_tasks,
Run_ run_task_range )
Template Parameters
Task_Integer type of the number of tasks.
Run_Function to execute a range of tasks.
Parameters
num_workersNumber of workers.
num_tasksNumber of tasks.
run_task_rangeFunction to iterate over a range of tasks within a worker.

By default, this is an alias to subpar::parallelize_range(). However, if the WEIGHTEDLOWESS_CUSTOM_PARALLEL function-like macro is defined, it is called instead. Any user-defined macro should accept the same arguments as subpar::parallelize_range().