wilkelab / ggridges

Ridgeline plots in ggplot2
https://wilkelab.org/ggridges
GNU General Public License v2.0
412 stars 31 forks source link

[Feature request] : fill the boundaries within #83

Open jorvlan opened 1 year ago

jorvlan commented 1 year ago

Is there a way to assign different colors to the boundaries within each violin? We have Likert data, and for each 'item' we would like to have a different color representation inside the violin (i.e., the boundaries you see in the figures below i.e., 2nd figure, which are different from the default 'quantiles' boundaries i.e., 1st figure). Schermafbeelding 2023-01-13 om 4 23 33 PM.

Any suggestions would be appreciated!

Please see the code (steps are included on how to create the figure below)!


library(ggplot2)
library(reshape2)
library(ggridges)

STEP 1: Create fake data for visualization of likert data

pre <- c(1,1,4,1,1,2,1,1,2,2,1,3,2,1,2,2,2,3,2,4,5,2,3,3,4,4,2,2,5,3,4,3,5,3,3,4,3,2,2,2,4,2,3,2,3,4,4,3,5,1,2,5,2,3,3,5,5,3,1,3,4,2,3,4,3,3,2,3,4,5,3,3,3,4,2,2,4,3,3,5,3,3,2,2,3,3,1,4,4,2,3,4,2,2,1,2,3,3,3,2,1,2,3,3,3,2,3,4,3,4,3,1,4,2,3,2,4,3,3,4,3,3,2,3,4,3,4,3,3,3)

post <- c(1,1,1,1,1,1,1,2,2,1,1,2,2,3,2,2,2,2,2,2,3,3,2,3,1,4,1,2,3,3,5,2,4,3,4,2,3,2,3,2,3,3,3,3,3,3,4,3,5,3,1,3,2,3,3,2,2,3,3,3,4,3,3,3,3,3,3,4,3,3,3,4,3,4,3,3,2,3,3,3,3,3,1,3,3,2,2,4,5,3,3,4,3,3,2,3,3,4,3,4,1,3,4,2,3,2,4,2,3,3,3,3,4,1,3,4,3,3,3,4,3,3,3,3,3,3,3,4,4,5)

STEP 2: Do some wrangling & labeling to set up the desired structure

likert_data <- data.frame(pre,post)

likert_data$id <- as.factor(as.character(rep(1:dim(likert_data)[1])))

likert_data <- reshape2::melt(likert_data, id.vars = "id")
colnames(likert_data)[2] <- "time"

likert_data$covariate <- -likert_data$value*2

likert_data$group <- c(rep("old", 65), rep("young", 65), rep("old", 65), rep("young", 65))#,
                # rep("old", 65), rep("young", 200), rep("old", 200), rep("young", 200))

likert_data$value[likert_data$group == "young"] <- likert_data$value[likert_data$group == "young"] + 1

likert_data$value[likert_data$group == "old" & likert_data$time == "t2"] <- likert_data$value[likert_data$group == "old" & 
likert_data$time == "t2"] -2

likert_data$jit <- jitter(likert_data$value, amount = .2)

STEP 3: Create bounds function that will define the boundaries for likert data in each violin

proportions <- table(likert_data$pre)/length(likert_data$pre)

4*0.107 + 1 + 4*0.261

abs_range <- abs(min(likert_data$pre)) + abs(max(likert_data$pre))

4*0.107 + 1 + 4*0.261 + 4*.37 + 4*.18 + 4*.07 #(you don't need the last boundary)

bounds <- function(x, ...){

  l_unique_min1 <- length(unique(x))-1
  vec <- as.numeric(rep(0, l_unique_min1))
  proportions <- as.numeric(table(x)/length(x))

  s <- 0
  for (i in 1:l_unique_min1){
    vec[i] <- proportions[i]*l_unique_min1 + s
    s <- vec[i]
  }

  vec <- vec + min(x)

  return(vec)
}

STEP 4: Change dataframe orientation

ct <- reshape2::melt(likert_data)

STEP 5: Plot the figure

ggplot(ct, aes(x = value, y = variable, fill = variable)) +
  geom_density_ridges(quantile_lines = T, quantile_fun = bounds, position = position_nudge(y=.2)) +
  geom_boxplot(width = .2, position = position_nudge(y= -.2)) +
  geom_point() +
  scale_x_continuous(limits=c(-15, 20)) 

a12bfaec-7260-4470-a072-175870e0fdcc