How to calculate a moving average in R

how-to
time series
Learn calculate a moving average in r with clear examples and explanations.
Published

March 26, 2026

Introduction

The slider package provides powerful functions for performing sliding window operations in R. It’s particularly useful for calculating rolling statistics, moving averages, and other analyses where you need to apply functions across overlapping subsets of your data. Use slider when you need more flexibility and control than base R’s rolling functions offer.

Installation and Setup

First, let’s load the required packages and check our slider version:

library(tidyverse)
library(slider)
library(palmerpenguins)

Let’s verify we’re using a recent version of slider:

packageVersion("slider")

This ensures we have access to all the latest slider functions and improvements.

Basic Sliding Window Operations

The core function slide() applies a function to a sliding window of your data. Let’s start with a simple numeric vector:

numbers <- c(1, 4, 6, 8, 10, 12, 15, 18)
slide(numbers, mean, .before = 2, .after = 0)

This calculates a 3-point moving average, looking at the current value and 2 values before it. The .before and .after arguments control the window size and position.

Sliding with Data Frames

Slider works seamlessly with data frames and the tidyverse. Let’s calculate rolling averages for penguin body mass:

penguins_clean <- penguins |> 
  filter(!is.na(body_mass_g)) |> 
  arrange(body_mass_g)

Now we’ll add a 5-point moving average using slide_dbl() for numeric output:

penguins_rolling <- penguins_clean |> 
  mutate(
    mass_rolling_mean = slide_dbl(
      body_mass_g, 
      mean, 
      .before = 2, 
      .after = 2
    )
  )

The slide_dbl() function returns a numeric vector, making it perfect for creating new columns with rolling statistics.

Different Window Sizes and Functions

You can easily change window sizes and apply different functions. Let’s calculate rolling minimums and maximums:

penguins_stats <- penguins_clean |> 
  mutate(
    mass_roll_min = slide_dbl(body_mass_g, min, .before = 4),
    mass_roll_max = slide_dbl(body_mass_g, max, .before = 4)
  )

This creates 5-point rolling windows (current value plus 4 before) to find the minimum and maximum values in each window.

Time-Based Sliding Windows

For time series data, you can use date-based windows. Let’s group by species and calculate rolling statistics:

penguins_by_species <- penguins |> 
  filter(!is.na(body_mass_g)) |> 
  group_by(species) |> 
  arrange(body_mass_g, .by_group = TRUE)

Now apply sliding functions within each group:

species_rolling <- penguins_by_species |> 
  mutate(
    roll_median = slide_dbl(body_mass_g, median, .before = 3),
    roll_sd = slide_dbl(body_mass_g, sd, .before = 3, .complete = TRUE)
  )

The .complete = TRUE argument ensures the function only runs when the window is completely filled, returning NA otherwise.

Advanced: Custom Functions and Multiple Columns

You can pass custom functions to slider operations. Let’s calculate the range (max - min) for sliding windows:

range_function <- function(x) {
  max(x, na.rm = TRUE) - min(x, na.rm = TRUE)
}

Apply this custom function to calculate rolling ranges:

penguins_range <- penguins_clean |> 
  mutate(
    mass_roll_range = slide_dbl(
      body_mass_g, 
      range_function, 
      .before = 2, 
      .after = 2
    )
  )

This creates a rolling measure of variability within each 5-point window around each observation.

Summary

The slider package offers flexible and intuitive functions for sliding window operations in R. Key functions include slide() for general operations, slide_dbl() for numeric results, and various window specifications using .before and .after. These tools are essential for time series analysis, smoothing data, and calculating rolling statistics in your data analysis workflows.