--- 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 LOESS processes data in fixed-size chunks with a configurable overlap. Points inside the overlap zone receive estimates from both adjacent chunks; the merge strategy decides how those two estimates are reconciled. ```text Chunk A: [=========|=====] Chunk B: [=====|=========] Overlap: [=====] ``` | 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 | High | Moderate | ![Merge strategy comparison](../man/figures/merge_comparison.svg) --- ## Average Takes the arithmetic mean of the left-chunk and right-chunk estimates in the overlap region. Fast and sufficient when both chunks have similar smoothing quality. **Use when**: Chunks are large and the overlap region has uniform data density. ```{r merge_1} library(rfastloess) set.seed(42) x <- seq(0, 2 * pi, length.out = 100) y <- sin(x) + rnorm(100, sd = 0.3) model <- StreamingLoess( chunk_size = 60, overlap = 20, merge_strategy = "average" ) invisible(process_chunk(model, x[1:60], y[1:60])) # The second chunk's overlap region (its first 20 points) is where # merge_strategy actually blends the two chunks' estimates. result <- process_chunk(model, x[61:100], y[61:100]) cat("Merged value in overlap region (average):\n") print(result$y[6]) ``` --- ## Take First Keeps only the left-chunk estimate in the overlap zone and discards the right-chunk estimate. Produces a left-flush output. **Use when**: You need final output values immediately after each chunk (no look-ahead revision); left-chunk context dominates. ```{r merge_2} model <- StreamingLoess( chunk_size = 60, overlap = 20, merge_strategy = "take_first" ) invisible(process_chunk(model, x[1:60], y[1:60])) result <- process_chunk(model, x[61:100], y[61:100]) cat("Merged value in overlap region (take_first):\n") print(result$y[6]) ``` --- ## Take Last Keeps only the right-chunk estimate in the overlap zone. The right chunk sees more of the surrounding data, so its estimates can be more accurate in the overlap region. **Use when**: Right-chunk context improves overlap quality; you are post-processing complete data rather than streaming in real time. ```{r merge_3} model <- StreamingLoess( chunk_size = 60, overlap = 20, merge_strategy = "take_last" ) invisible(process_chunk(model, x[1:60], y[1:60])) result <- process_chunk(model, x[61:100], y[61:100]) cat("Merged value in overlap region (take_last):\n") print(result$y[6]) ``` --- ## Weighted Average Assigns each overlap point a weight proportional to its proximity to the centre of its respective chunk: points near the left-chunk centre favour the left estimate; points near the right-chunk centre favour the right. Minimises boundary artefacts. **Use when**: Minimising boundary artefacts is more important than speed; moderate overlap (10–20% of chunk size) is used. ```{r merge_4} model <- StreamingLoess( chunk_size = 60, overlap = 20, merge_strategy = "weighted_average" ) invisible(process_chunk(model, x[1:60], y[1:60])) result <- process_chunk(model, x[61:100], y[61:100]) cat("Merged value in overlap region (weighted_average):\n") print(result$y[6]) ``` --- ## 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"` | > **Overlap size matters:** A larger overlap gives the merge strategy more room > to blend, reducing boundary artefacts regardless of the strategy chosen. A > good starting point is 10% of `chunk_size`. --- ## Choosing Chunk Size and Overlap ```{r merge_5} # Rule of thumb: overlap = fraction * chunk_size fraction <- 0.3 chunk_size <- 5000 overlap <- ceiling(fraction * chunk_size) # 1500 model <- StreamingLoess( 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)) ``` ```{r session-info} sessionInfo() ```