WeightedLowess
A C++ library for LOWESS with various weighting schemes
|
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) |
Namespace for LOWESS functions.
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.
Data_ | Floating-point type of the data. |
[in] | x_fit | Pointer to an array of x-coordinates for the fitted trend from compute() . This should be sorted in increasing order. |
windows_fit | Precomputed windows for anchor points, created by calling define_windows() on x_fit . | |
num_points_out | Number of points to be interpolated. | |
[in] | x_out | Pointer 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 . |
x_out
to its corresponding segment, where possible. This can be re-used for multiple interpolate()
calls with different fitted
values. 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.
Data_ | Floating-point type of the data. |
num_points | Number of points. | |
[in] | x | Pointer 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] | y | Pointer to an array of num_points y-coordinates. |
opt | Further options. |
Results
object containing the fitted values and robustness weights. 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.
Data_ | Floating-point type of the data. |
num_points | Number of points. | |
[in] | x | Pointer 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] | y | Pointer to an array of num_points y-coordinates. |
[out] | fitted | Pointer to an output array of length num_points , in which the fitted values of the smoother can be stored. |
[out] | robust_weights | Pointer 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. |
opt | Further options. |
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.
Data_ | Floating-point type of the data. |
num_points | Number of points. | |
[in] | x | Pointer 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 .) |
windows | Precomputed 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] | y | Pointer to an array of num_points y-coordinates. |
[out] | fitted | Pointer to an output array of length num_points , in which the fitted values of the smoother can be stored. |
[out] | robust_weights | Pointer 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. |
opt | Further 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 . |
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.
Data_ | Floating-point type of the data. |
num_points | Number of points. | |
[in] | x | Pointer 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.) |
opt | Further 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 . |
|
inline |
assigned_out | Assignment of each point-to-be-interpolated to a inter-anchor segment, produced by assign_to_segments() . |
x_out
that can be safely interpolated, i.e., do not lie beyond x_fit
. 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.
Data_ | Floating-point type of the data. |
[in] | x_fit | Pointer to an array of x-coordinates for the fitted trend from compute() . This should be sorted in increasing order. |
windows_fit | Precomputed windows for anchor points, created by calling define_windows() on x_fit . | |
[in] | fitted_fit | Pointer 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_out | Pointer to an array of x-coordinates of the points to be interpolated. This should be sorted in increasing order. |
[in] | assigned_out | Assignment 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_out | Pointer 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_threads | Number of threads to use. |
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.
Data_ | Floating-point type of the data. |
[in] | x_fit | Pointer to an array of x-coordinates for the fitted trend from compute() . This should be sorted in increasing order. |
windows_fit | Precomputed windows for anchor points, created by calling define_windows() on x_fit . | |
[in] | fitted_fit | Pointer 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_out | Number of points to be interpolated. | |
[in] | x_out | Pointer to an array of x-coordinates of the points to be interpolated. This should be sorted in increasing order. |
[out] | fitted_out | Pointer 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_threads | Number of threads to use. |
get_interpolation_boundaries()
for details. void WeightedLowess::parallelize | ( | const int | num_workers, |
const Task_ | num_tasks, | ||
Run_ | run_task_range ) |
Task_ | Integer type of the number of tasks. |
Run_ | Function to execute a range of tasks. |
num_workers | Number of workers. |
num_tasks | Number of tasks. |
run_task_range | Function 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()
.