--- title: "Merge Strategies" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Merge Strategies} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ## Overview Streaming LOWESS processes data in fixed-size chunks with a configurable overlap. Points inside the overlap zone are fitted twice — once by the left chunk and once by the right chunk. The `merge_strategy` decides how those two estimates are combined. ```text Chunk A: [=========|=====] Chunk B: [=====|=========] Overlap: [=====] ↑ merge_strategy applied here ``` | Strategy | Method | Robustness | Speed | | --- | --- | --- | --- | | `"average"` | Simple mean of both estimates | Low | Fastest | | `"take_first"` | Left-chunk estimate only | Low | Fastest | | `"take_last"` | Right-chunk estimate only | Low | Fastest | | `"weighted_average"` | Distance-weighted mean (default) | High | Moderate | ![Merge strategy comparison](../man/figures/merge_comparison.svg) --- ## Weighted Average (Default) Blends left- and right-chunk estimates using distance-based weights. Points closer to the centre of each chunk get higher weight. **Use when**: General-purpose streaming; most reliable option. ```{r merge_1} library(rfastlowess) set.seed(42) x <- seq(0, 2 * pi, length.out = 100) y <- sin(x) + rnorm(100, sd = 0.3) x_chunk <- x[seq_len(50)] y_chunk <- y[seq_len(50)] model <- StreamingLowess( chunk_size = 5000, overlap = 500, merge_strategy = "weighted_average" ) result <- process_chunk(model, x_chunk, y_chunk) cat("First 6 smoothed values (weighted_average strategy):\n") print(head(result$y)) ``` --- ## Average Takes the arithmetic mean of the left-chunk and right-chunk estimates in the overlap region. **Use when**: Chunks are large and the overlap region has uniform data density. ```{r merge_2} model <- StreamingLowess( chunk_size = 5000, overlap = 500, merge_strategy = "average" ) result <- process_chunk(model, x_chunk, y_chunk) cat("First 6 smoothed values (average strategy):\n") print(head(result$y)) ``` --- ## Take First Uses only the left-chunk estimate in the overlap region. **Use when**: The left chunk has a larger context window and is expected to be more accurate at the overlap boundary. ```{r merge_3} model <- StreamingLowess( chunk_size = 5000, overlap = 500, merge_strategy = "take_first" ) result <- process_chunk(model, x_chunk, y_chunk) cat("First 6 smoothed values (take_first strategy):\n") print(head(result$y)) ``` --- ## Take Last Uses only the right-chunk estimate in the overlap region. **Use when**: The right chunk is expected to provide better context (e.g., more data follows). ```{r merge_4} model <- StreamingLowess( chunk_size = 5000, overlap = 500, merge_strategy = "take_last" ) result <- process_chunk(model, x_chunk, y_chunk) cat("First 6 smoothed values (take_last strategy):\n") print(head(result$y)) ``` --- ## Choosing Chunk Size and Overlap | Consideration | Recommendation | | --- | --- | | Memory limit | `chunk_size` = largest chunk that fits comfortably | | Edge accuracy | `overlap` ≥ `fraction × chunk_size` | | Speed | Larger chunks → fewer merges → faster | ```{r merge_5} # Rule of thumb: overlap = fraction * chunk_size fraction <- 0.3 chunk_size <- 5000 overlap <- ceiling(fraction * chunk_size) # 1500 model <- StreamingLowess( fraction = fraction, chunk_size = chunk_size, overlap = overlap, merge_strategy = "weighted_average" ) cat(sprintf("overlap = %d points (%.0f%% of chunk)\n", overlap, 100 * overlap / chunk_size)) ``` --- ## Choosing a Strategy | Situation | Recommended Strategy | | --- | --- | | General purpose | `"weighted_average"` | | Maximum throughput | `"average"` | | Immediate finalised output | `"take_first"` | | Post-processing, right context better | `"take_last"` | | Minimising boundary artefacts | `"weighted_average"` | ```{r session-info} sessionInfo() ```