ggplot2 geom_histogram вычерчивает бары божественности из выборки распределения смеси с 2 взвешенными распределениями - PullRequest
0 голосов
/ 06 сентября 2018

Перво-наперво, я получил 2 смешанных дистрибутива (они имеют смешанную часть), и я знал, что образцы взяты из какого дистрибутива. Затем я хочу построить гистограмму в соответствии с плотностью образцов и распределением смеси.

Давайте перейдем к коду ( seg 1 ):

library(mixtools)

# two components
set.seed(1)    # for reproducible example
b1 <- rnorm(900000, mean=8, sd=2) # samples
b2 <- rnorm(100000, mean=17, sd=2)

# densities corresponding to samples
d = dnorm(c(b1, b2), mean = 8, sd = 2)*.9 + dnorm(c(b1, b2), mean = 17, sd = 2)*.1 

# ground truth
b <- data.frame(ss=c(b1,b2), dd=d, gg=factor(c(rep(1, length(b1)), rep(2, length(b2))))) 

# sample from mixed distribution
c <- b[sample(nrow(b), 500000),] 

library(ggplot2)
ggplot(data = c, aes(x = ss)) +
  geom_histogram(aes(y = stat(density)), binwidth = .5, alpha = .3, position="identity") +
  geom_line(data = c, aes(x = ss, y = dd), color = "red", inherit.aes = FALSE)

этот результат в порядке: вот так

Но я хочу заполнить цвет в соответствии с группой образцов. Поэтому я меняю код ( seg 2 ):

ggplot(data=c, aes(x=ss)) +
  geom_histogram(aes(y=stat(density), fill=gg, color=gg), 
                 binwidth=.5, alpha=.3, position="identity") +
  geom_line(data=c, aes(x=ss, y=dd), color="red", inherit.aes=FALSE)

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

Затем я нашел несколько методов, таких как this ( seg 3 ):

breaks = seq(min(c$ss), max(c$ss), .5) # form cut points
bins1 = cut(with(c, ss[gg==1]), breaks) # form intervals by cutting
bins2 = cut(with(c, ss[gg==2]), breaks)
cnt1 = sapply(split(with(c, ss[gg==1]), bins1), length) # assign points to its interval
cnt2 = sapply(split(with(c, ss[gg==2]), bins2), length)
h = data.frame(
  x = head(breaks, -1)+.25,
  dens1 = cnt1/sum(cnt1,cnt2), # height of density bar
  dens2 = cnt2/sum(cnt1,cnt2)
  # weight = sapply(split(samples.mixgamma$samples, bins), sum)
)
ggplot(h) +
  geom_bar(aes(x, dens1), fill="red", alpha = .3, stat="identity") +
  geom_bar(aes(x, dens2), fill="blue", alpha = .3, stat="identity") +
  geom_line(data=c, aes(x=ss, y=dd), color="red", inherit.aes=FALSE)

или установите y=stat(count)/sum(stat(count)) вот так ( seg 4 ):

ggplot(data=c, aes(x=ss)) +
  geom_histogram(aes(y=stat(count)/sum(stat(count)), fill=gg, color=gg), 
                 binwidth=.5, alpha=.3, position="identity") +
  geom_line(data=c, aes(x=ss, y=dd), color="red", inherit.aes=FALSE)

результаты одинаковы и неверны, все столбцы примерно в два раза меньше сегмента 1.

Так что, если я хочу заполнить 2 группы разными цветами, например, сегментом 2, и правильной пропорцией, например сегментом 1, и избежать ошибки, такой как сегмент 3 и сегмент 4, что я могу сделать?

Большое спасибо!

plot

Решение заключается в том, что: плотность вероятности следует рассчитывать как y=stat(count)/.5/sum(stat(count)). Я только делаю нормализацию, но не делю массу на ее объем. Поэтому ответ, такой как this и seg 3 , необходимо изменить

...