Предотвращение неправильных графиков плотности при раскраске гистограмм по группам - PullRequest
0 голосов
/ 24 января 2019

на основе некоторых фиктивных данных я создал гистограмму с графиком божественности

set.seed(1234)
wdata = data.frame(
  sex = factor(rep(c("F", "M"), each=200)),
  weight = c(rnorm(200, 55), rnorm(200, 58))
)
a <- ggplot(wdata, aes(x = weight))

a + geom_histogram(aes(y = ..density..,
                       # color = sex
                       ), 
                   colour="black",
                   fill="white",
                   position = "identity") +
  geom_density(alpha = 0.2,
               # aes(color = sex)
               ) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF"))

Basic Result

Гистограмма weight должна быть цветной, соответствующей sex, поэтому я использую aes(y = ..density.., color = sex) для geom_histogram():

a + geom_histogram(aes(y = ..density..,
                       color = sex
                       ), 
                   colour="black",
                   fill="white",
                   position = "identity") +
  geom_density(alpha = 0.2,
               # aes(color = sex)
               ) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF"))

Scaled individual histograms (not desired)

Как я хочу, график плотности остается неизменным (в целом для обеих групп), но гистограммы увеличиваются (и, похоже, теперь рассматриваются по отдельности):

Как мне предотвратить это? Мне нужны индивидуально окрашенные гистограммы, но график плотности соединений для всех групп окраски.

P.S. Использование aes(color = sex) для geom_density() возвращает все обратно к исходным шкалам, но я не хочу, чтобы отдельные графики плотности (как показано ниже):

a + geom_histogram(aes(y = ..density..,
                       color = sex
                       ), 
                   colour="black",
                   fill="white",
                   position = "identity") +
  geom_density(alpha = 0.2,
               aes(color = sex)
               ) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF"))

Individual densities (not desired)

EDIT:

Как было предложено, деление на количество групп в эстетике geom_histogram() с y = ..density../2 может приблизить решение. Тем не менее, это работает только с симметричными распределениями, как в первом выводе ниже:

a + geom_histogram(aes(y = ..density../2,
                       color = sex
                       ), 
                   colour="black",
                   fill="white",
                   position = "identity") +
  geom_density(alpha = 0.2,
               ) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF"))

что дает

Solution

Меньше симметричных распределений, однако, может вызвать проблемы при использовании этого подхода. См. Ниже, где для 5 групп использовалось y = ..density../5. Сначала оригинал, потом манипуляция (с position = "stack"): Original

Divided by 5

Поскольку распределение тяжелое слева, деление на 5 недооценивает слева и завышает справа.

РЕДАКТИРОВАТЬ 2: РЕШЕНИЕ

Как предположил Эндрю, приведенный ниже (полный) код решает проблему:

library(ggplot2)
set.seed(1234)
wdata = data.frame(
  sex = factor(rep(c("F", "M"), each = 200)),
  weight = c(rnorm(200, 55), rnorm(200, 58))
)

binwidth <- 0.25
a <- ggplot(wdata,
            aes(x = weight,
                # Pass binwidth to aes() so it will be found in
                # geom_histogram()'s aes() later
                binwidth = binwidth))

# Basic plot w/o colouring according to 'sex'
a + geom_histogram(aes(y = ..density..),
                   binwidth = binwidth,
                   colour = "black",
                   fill = "white",
                   position = "stack") +
  geom_density(alpha = 0.2) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF")) +
  # Use fixed scale for sake of comparability
  scale_x_continuous(limits = c(52, 61)) +
  scale_y_continuous(limits = c(0, 0.25))


# Plot w/ colouring according to 'sex'
a + geom_histogram(aes(x = weight,
                       # binwidth will only be found if passed to
                       # ggplot()'s aes() (as above)
                       y = ..count.. / (sum(..count..) * binwidth),
                       color = sex),
                   binwidth = binwidth,
                   fill="white",
                   position = "stack") +
  geom_density(alpha = 0.2) +
  scale_color_manual(values = c("#868686FF", "#EFC000FF")) +
  # Use fixed scale for sake of comparability
  scale_x_continuous(limits = c(52, 61)) +
  scale_y_continuous(limits = c(0, 0.25)) +
  guides(color = FALSE)

Примечание: binwidth = binwidth необходимо передать ggplot() aes(), в противном случае предопределенное binwidth не будет найдено geom_histogram() aes(). Далее указывается position = "stack", так что обе версии гистограммы сравнимы. Графики для фиктивных данных и более сложное распределение ниже:

Correct, ungrouped, simple data

Correct, grouped, simple data

Correct, ungrouped, more complex distribution

Correct, grouped, more complex distribution

Решено - Спасибо за помощь!

1 Ответ

0 голосов
/ 25 января 2019

Я не думаю, что вы можете сделать это, используя y=..density.., но вы можете воссоздать то же самое, как это ...

binwidth <- 0.25 #easiest to set this manually so that you know what it is

a + geom_histogram(aes(y = ..count.. / (sum(..count..) * binwidth),
                       color = sex), 
                   binwidth = binwidth,
                   fill="white",
                   position = "identity") +
    geom_density(alpha = 0.2) +
    scale_color_manual(values = c("#868686FF", "#EFC000FF"))

enter image description here

...