I have a 2 min data set sampled at 10 Hz that I want to plot like an ECG in R: I want to create a plot with a 30 s window, plot the first 30 s from left to right in real time, then after 30 s, the data are plotted from the left to right again, progressively replacing the previous curve. With like a 1s interval between the old curve and the new one. And export as mp4. For now, I manage to have an animated plot in R, but not something like an ECG.
A reproducible data set:
dt <- 0.1
freq <- 12 / 60
start <- as.POSIXct("2025-11-19 13:00:00", tz = "UTC") + 0.001
t_sec <- seq(from = 0, by = dt, length.out = n_rows)
times <- start + t_sec
signal <- sin(2 * pi * freq * t_sec)
rep_dataset <- data.frame(Time = times,Individual = signal)
head(rep_dataset, 5)
time Individual
1 13:00:00.000 0.0000000
2 13:00:00.100 0.1253331
3 13:00:00.200 0.2486899
4 13:00:00.300 0.3681245
5 13:00:00.401 0.4817538
My current code:
library("dplyr")
library("lubridate")
library("ggplot2")
library("gganimate")
library("pracma")
library("tuneR")
library("seewave")
segment <- rep_dataset
# Normalize time relative to start
segment$Time0 <- as.numeric(segment$Time - segment$Time[1])
peak_data <- findpeaks(segment$Individual, minpeakheight = mean(segment$Individual) + sd(segment$Individual))
peak_idx <- peak_data[,2]
segment$peak <- FALSE
segment$peak[peak_idx] <- TRUE
#ECG-type line
offsets <- c(-3, -1.5, 0, 1.5, 3)
ECG <- ggplot(segment, aes(x = Time0, y = Individual))
for(off in offsets){
ECG <- ECG + geom_line(
aes(y = Individual + off),
color = rgb(0.2, 0.4, 1, 0.15),
linewidth = 1.5
)
}
ECG <- ECG + geom_line(
aes(y = Individual),
color = rgb(0.2, 0.4, 1, 1),
linewidth = 1.5
)
# Add labels and animate
ECG <- ECG +
theme_minimal(base_size = 15) +
theme(
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray25", linewidth = 0.2),
plot.background = element_rect(fill = "black", color = NA),
panel.background = element_rect(fill = "black", color = NA),
text = element_text(color = "white"),
axis.text = element_text(color = "white")
) +
labs(subtitle = "{sprintf('%.2f', frame_along)}",
x = "",
y = "Electrical current"
) +
transition_reveal(Time0)
#render a mp4 file
fps <- 10
nframes <- nrow(segment)
animate(
ECG,
nframes = nframes,
fps = fps,
renderer = av_renderer("my_video.mp4"),
width = 1000,
height = 480)



gganimateinside a loop to produce frames looping through the segments of 30s to essentially animate one plot for each "pulse", and in the end create the animation using all the images generated.