Гистограмма в процентах с facet_wrap - PullRequest
0 голосов
/ 07 октября 2018

Я пытаюсь объединить процентную гистограмму с facet_wrap, но проценты рассчитываются не по группам, а по всем данным.Я хотел бы, чтобы каждая гистограмма показывала распределение в группе, а не относительно всего населения.Я знаю, что можно сделать несколько графиков и объединить их с multiplot.

library(ggplot2)
library(scales)
library(dplyr)

set.seed(1)
df <- data.frame(age = runif(900, min = 10, max = 100),
                 group = rep(c("a", "b", "c", "d", "e", "f", "g", "h", "i"), 100))

tmp <- df %>%
  mutate(group = "ALL")

df <- rbind(df, tmp)

ggplot(df, aes(age)) + 
  geom_histogram(aes(y = (..count..)/sum(..count..)), binwidth = 5) + 
  scale_y_continuous(labels = percent ) + 
  facet_wrap(~ group, ncol = 5) 

Вывод: output plot

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Хотя кажется, что facet_wrap не выполняет специальный расчет geom_histogram процента в каждом подмножестве, рассмотрите возможность составления списка графиков отдельно, а затем распределите их по сетке.

В частности, вызовите by длязапустите ваши ggplots в подмножествах group и затем вызовите gridExtra::grid.arrange() (метод фактического пакета), чтобы несколько имитировать facet_wrap:

library(ggplot2)
library(scales)
library(gridExtra)

...

grp_plots <- by(df, df$group, function(sub){
  ggplot(sub, aes(age)) + 
    geom_histogram(aes(y = (..count..)/sum(..count..)), binwidth = 5) + 
    scale_y_continuous(labels = percent ) + ggtitle(sub$group[[1]]) +
    theme(plot.title = element_text(hjust = 0.5))
})

grid.arrange(grobs = grp_plots, ncol=5)

Plot Output


Однако, чтобы избежать повторяющихся осей Y и X, рассмотрите возможность условной установки theme в by вызове, предполагая, что вы знаете свои группы заранее, и их число достаточно разумное.,

grp_plots <- by(df, df$group, function(sub){

  # BASE GRAPH
  p <- ggplot(sub, aes(age)) + 
    geom_histogram(aes(y = (..count..)/sum(..count..)), binwidth = 5) + 
    scale_y_continuous(labels = percent ) + ggtitle(sub$group[[1]])

  # CONDITIONAL theme() CALLS
  if (sub$group[[1]] %in% c("a")) {
    p <- p + theme(plot.title = element_text(hjust = 0.5), axis.title.x = element_blank(), 
                  axis.text.x = element_blank(), axis.ticks.x = element_blank())
  }
  else if (sub$group[[1]] %in% c("f")) {
    p <- p + theme(plot.title = element_text(hjust = 0.5))
  }
  else if (sub$group[[1]] %in% c("b", "c", "d", "e")) {
    p <- p + theme(plot.title = element_text(hjust = 0.5), axis.title.y = element_blank(), 
                   axis.text.y = element_blank(), axis.ticks.y = element_blank(),
                   axis.title.x = element_blank(), axis.text.x = element_blank(), 
                   axis.ticks.x = element_blank())
  }
  else {
    p <- p + theme(plot.title = element_text(hjust = 0.5), axis.title.y = element_blank(), 
                   axis.text.y = element_blank(), axis.ticks.y = element_blank())
  }
  return(p)
})

grid.arrange(grobs=grp_plots, ncol=5)

Plot Output

0 голосов
/ 07 октября 2018

Попробуйте с y = stat(density) (или y = ..density.. до ggplot2 версии 3.0.0) вместо y = (..count..)/sum(..count..)

ggplot(df, aes(age, group = group)) + 
  geom_histogram(aes(y = stat(density) * 5), binwidth = 5) + 
  scale_y_continuous(labels = percent ) +
  facet_wrap(~ group, ncol = 5)

enter image description here

из ?geom_histogramm в разделе «Вычисляемые переменные»

плотность: плотность точек в ячейке, масштабированная для интегрирования до 1

Мы умножаем на 5 (ширина ячейки), потому чтоось y - это плотность (площадь объединяется в 1), а не в процентах (сумма высот равна 1), см. комментарий Хэдли (благодаря @MariuszSiatka).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...