How to smooth out a time-series geom_area with fill in ggplot?

I have the following graph and code:

Graph

ggplot(long2, aes(x = DATA, y = value, fill = variable)) + geom_area(position="fill", alpha=0.75) +
      scale_y_continuous(labels = scales::comma,n.breaks = 5,breaks = waiver()) +
      scale_fill_viridis_d() +
      scale_x_date(date_labels = "%b/%Y",date_breaks = "6 months") +
      ggtitle("Proporcions de les visites, només 9T i 9C") +
      xlab("Data") + ylab("% visites") + 
      theme_minimal() + theme(legend.position="bottom") + guides(fill=guide_legend(title=NULL)) +

        annotate("rect", fill = "white", alpha = 0.3, 
        xmin = as.Date.character("2020-03-16"), xmax = as.Date.character("2020-06-22"),
        ymin = 0, ymax = 1)

But it has some sawtooth, how am I supposed to smooth it out?

Upvotes: 0

Views: 308

Answers (1)

teunbrand
teunbrand

Reputation: 38013

I believe your situation is roughly analogous to the following, wherein we have missing x-positions for one group, but not the other at the same position. This causes spikes if you set position = "fill".

library(ggplot2)

x <- seq_len(100)

df <- data.frame(
  x = c(x[-c(25, 75)], x[-50]),
  y = c(cos(x[-c(25, 75)]), sin(x[-50])) + 5,
  group = rep(c("A", "B"), c(98, 99))
)

ggplot(df, aes(x, y, fill = group)) +
  geom_area(position = "fill")

To smooth out these spikes, it has been suggested to linearly interpolate the data at the missing positions.

# Find all used x-positions
ux <- unique(df$x)

# Split data by group, interpolate data groupwise
df <- lapply(split(df, df$group), function(xy) {
  approxed <- approx(xy$x, xy$y, xout = ux)
  data.frame(x = ux, y = approxed$y, group = xy$group[1])
})
# Recombine data
df <- do.call(rbind, df)

# Now without spikes :)
ggplot(df, aes(x, y, fill = group)) +
  geom_area(position = "fill")

Created on 2022-06-17 by the reprex package (v2.0.1)

P.S. I would also have expected a red spike at x=50, but for some reason this didn't happen.

Upvotes: 2

Related Questions