Построение нормальных распределений на хребтовой диаграмме с ggridges

Мне немного неловко задавать этот вопрос, но я потратил большую часть своего рабочего дня, пытаясь найти решение, и вот я ...

Я стремлюсь к простому линейному графику нескольких нормальных распределений, которые рассчитываются на основе заданных средних значений и SD в моих данных, как в этом примере:

case_number    caseMean    caseSD
case1          0           1
case2          1           2
case3          3           3

Все примеры, которые я нашел, работают с сериями измерений, как в примере с температурами в Линкольне, штат Северная Каролина: Пример графика хребта https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html, и я не могу заставить их работать.

Что касается моего опыта работы с R, я не полный идиот, когда дело доходит до анализа данных, но правильная визуализация - это то, чему я очень хочу научиться, но, к сожалению, мне нужно скорее решение моей проблемы.

Большое спасибо за Вашу помощь!


person Klaus Peter    schedule 04.06.2019    source источник


Ответы (2)


Edit - добавил точный теоретический ответ.

Вот способ использования dnorm для построения точных нормальных кривых в соответствии с этими спецификациями:

library(tidyverse); library(ggridges)
n = 100
df3 <- df %>%
  mutate(low  = caseMean - 3 * caseSD, high = caseMean + 3 * caseSD) %>%
  uncount(n, .id = "row") %>%
  mutate(x    = (1 - row/n) * low + row/n * high, 
         norm = dnorm(x, caseMean, caseSD))
ggplot(df3, aes(x, case_number, height = norm)) +
  geom_ridgeline(scale = 3)

введите здесь описание изображения


Подобно ответу Sada93, используя dplyr и tidyr:

library(tidyverse); library(ggridges)
n = 50000
df2 <- df %>% 
  uncount(n) %>%
  mutate(value = rnorm(n(), caseMean, caseSD))
ggplot(df2, aes(x = value, y = case_number)) + geom_density_ridges()

введите здесь описание изображения

образец данных:

df <- read.table(
  header = T, 
  stringsAsFactors = F,
  text = "case_number    caseMean    caseSD
case1          0           1
case2          1           2
case3          3           3")
person Jon Spring    schedule 04.06.2019
comment
Это все, на что я мог надеяться, спасибо вам всем огромное! - person Klaus Peter; 04.06.2019

Вам нужно создать новый фрейм данных с фактическими значениями распределения, а затем использовать ggridges следующим образом:

library(ggplot2)
library(ggridges)

data = data.frame(case = c("case1","case2","case3"),caseMean = c(0,1,3),caseSD = c(1,2,3))

#Create 100 rows for each mean and SD

data_plot = data.frame(case = character(),value = numeric())
n = 100
for(i in 1:nrow(data)){

  case = data$case[i]
  mean = data$caseMean[i]
  sd = data$caseSD[i]

  val = rnorm(n,mean,sd)

  data_plot = rbind(data_plot,
                    data.frame(case = rep(case,n),
                               value = val))
}

ggplot(data = data_plot,aes(x = value,y = case))+geom_density_ridges()

person Sada93    schedule 04.06.2019
comment
Большое спасибо за это предложение! Для моих нужд сейчас этого достаточно, хотя мне нужно увеличивать количество точек данных для каждого случая, когда оно имитирует нормальное распределение, что занимает некоторое время на моей старой машине. Возможно, у кого-то есть дополнительные предложения, поэтому я пока оставляю это открытым. Еще раз большое спасибо! - person Klaus Peter; 04.06.2019