I wonder if you can help.

# create the baseline (on which the for example a model is fitted form which one can sample and derive the uncertainity of the cycle)

    x <- "
Groups  5Y(average) 2016    2017    2018    2019    2020
1   26  21  23  26  28  31
2   21  20  21  22  22  22
3   26  28  28  27  26  24
4   17  19  18  16  15  15
5   7   9   8   7   6   5
6   2   2   2   1   1   1
7   1   0   1   0   1   1
8   1   1   1   0   0   0
"
  
data <- read.table(
    textConnection(object = x),
    header = TRUE,
    sep = "",
    stringsAsFactors = FALSE
)
data
    
ccf.list <- list()
for(i in 1:nrow(data)){
    ccf.res <- ccf(ts(data)[i,],ts(rev(data))[i,])
    ccf.list[[i]] <- data.frame(group=i, lag=ccf.res$lag, ccf=ccf.res$acf)
}

cycl <- do.call(rbind, ccf.list)
cycl

q.cycle <- do.call(data.frame, with(cycl[ ,c("lag","ccf")], aggregate(cycl[ ,c("lag","ccf")], list(lag), quantile)))
q.cycle
q.cycle.short <- q.cycle[ ,c(1,c(7:ncol(q.cycle)))] # pick up teh 75% percentile as the baseline as the curve seems to fit the best (full down and up cycle)

# to long format for plotting all percentiles
q.cycle.long <- data.frame(lag=matrix(as.matrix(q.cycle.short[1]), ncol=1), ccf=matrix(as.matrix(q.cycle.short[-1]), ncol=1))
q.cycle.long$year <- with(q.cycle.long, rep(1:11,nrow(q.cycle.long)/11))
tail(q.cycle.long)
   
plot(ccf.75. ~ 1, data=q.cycle.short, col="red", type="b", pch=19, lwd=3, ylim=c(-0.5,0.5))
lines(ccf ~ year, data=q.cycle.long, col="darkgray")
abline(h=0, col="blue", lwd=3, lty=3)

enter image description here

Here this would be possible if a parametric model would exist and just new.data=data.frame(years=1:10) would allow to extrapolate. But how to get there sensibly?

Below you find very simple attempt which based on first inspection seems to be plausible but there must be better (and correct) way to estimate it.

Sample data and the attempt (in r):

The data are percentages per group and represent the proportion of observations per group of the overall dataset per year (each column should sum to 100% or 1, but because of rounding some might be slightly over 100%). The below data contains 5Y of data and its collected once a year (end of year) and this sample (patients in given category) shifts across these groups. (due to health risk).

This current data represents currently lower cycle with lower health risk. The cyclicality is expected due to exogenous factors and have roughly (length of upper or down cycle between 5-10 years. Unfortunately there is limited data on this migration and its expected (assumed) that the current down cycle its just reverse to explain how the upper cycle looks like (just a mirror).

The graph below is derived form this code:

plot(ccf ~ lag, data=cycl[cycl$group==1, ], col=1, type="l", ylim=c(-1,1))
with(cycl, by(cycl, group, function(x) lines(ccf ~ lag, data=x, col=group)))

enter image description here