Sobreposição de histogramas com ggplot2 em R


124

Eu sou novo no R e estou tentando plotar 3 histogramas no mesmo gráfico. Tudo funcionou bem, mas meu problema é que você não vê onde 2 histogramas se sobrepõem - eles parecem um pouco cortados.

Quando faço gráficos de densidade, parece perfeito: cada curva é cercada por uma linha de quadro preta e as cores parecem diferentes quando as curvas se sobrepõem.

Alguém pode me dizer se algo semelhante pode ser alcançado com os histogramas da 1ª foto? Este é o código que estou usando:

lowf0 <-read.csv (....)
mediumf0 <-read.csv (....)
highf0 <-read.csv(....)
lowf0$utt<-'low f0'
mediumf0$utt<-'medium f0'
highf0$utt<-'high f0'
histogram<-rbind(lowf0,mediumf0,highf0)
ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

3
Os hiperlinks para o histograma e a trama densidade são quebradas
Daghan ---

Respostas:


115

Seu código atual:

ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

é dizer ggplotpara a construção de um histograma usando todos os valores em f0e em seguida, as barras de cor da presente único histograma de acordo com a variável utt.

Em vez disso, o que você deseja é criar três histogramas separados, com mistura alfa para que sejam visíveis um pelo outro. Portanto, você provavelmente deseja usar três chamadas separadas para geom_histogram, onde cada uma obtém seu próprio quadro de dados e preenche:

ggplot(histogram, aes(f0)) + 
    geom_histogram(data = lowf0, fill = "red", alpha = 0.2) + 
    geom_histogram(data = mediumf0, fill = "blue", alpha = 0.2) +
    geom_histogram(data = highf0, fill = "green", alpha = 0.2) +

Aqui está um exemplo concreto com alguma saída:

dat <- data.frame(xx = c(runif(100,20,50),runif(100,40,80),runif(100,0,30)),yy = rep(letters[1:3],each = 100))

ggplot(dat,aes(x=xx)) + 
    geom_histogram(data=subset(dat,yy == 'a'),fill = "red", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'b'),fill = "blue", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'c'),fill = "green", alpha = 0.2)

que produz algo parecido com isto:

insira a descrição da imagem aqui

Editado para corrigir erros de digitação; você queria preencher, não cor.


7
Isso não funciona quando o subconjunto tem tamanho diferente. Alguma idéia de como resolver isso? (Por exemplo, use dados com 100 pontos em "a", 50 em "b").
Jorge Leitao

3
Uma desvantagem dessa abordagem é que tive dificuldade em exibir uma legenda (embora isso possa ser devido à minha falta de conhecimento). A outra resposta abaixo de @kohske exibirá, por padrão, uma legenda que pode ser modificada (junto com as cores específicas exibidas no histograma) com, por exemplo scale_fill_manual().
Michael Ohlrogge 11/09/16

1
exatamente, como podemos adicionar legenda a isso?
21717 shenglih

1
@shenglih Para uma lenda, a resposta de kohske abaixo é melhor. Sua resposta também é geralmente melhor.
joran

de onde vem o f0?
Alan

256

Usando os dados de amostra de @ joran,

ggplot(dat, aes(x=xx, fill=yy)) + geom_histogram(alpha=0.2, position="identity")

observe que a posição padrão de geom_histogramé "pilha".

veja "ajuste de posição" desta página:

docs.ggplot2.org/current/geom_histogram.html


30
Eu acho que isso deve ser a resposta superior uma vez que evita a repetição de código
kfor

6
position = 'identity'não é apenas uma resposta mais legível, é mais agradável com gráficos mais complicados, como chamadas mistas para aes()e aes_string().
Rensa

2
Essa resposta também exibirá automaticamente uma legenda para as cores, enquanto a resposta de @joran não. A legenda pode ser modificada usando, por exemplo scale_fill_manual(). Esta função também pode ser usada para modificar as cores nos histogramas.
Michael Ohlrogge 11/09/16

4
Além disso, verifique se a variável usada fillé um fator.
hhh

9
Pessoalmente, acho que o stackoverflow deve listar a resposta mais votada primeiro. A "resposta correta" representa apenas a opinião de uma pessoa.
daknowles

25

Embora apenas algumas linhas sejam necessárias para plotar histogramas múltiplos / sobrepostos no ggplot2, os resultados nem sempre são satisfatórios. É necessário o uso adequado de bordas e cores para garantir que o olho possa diferenciar os histogramas .

As funções a seguir equilibram cores de borda, opacidades e gráficos de densidade sobreposta para permitir que o visualizador se diferencie entre distribuições .

Histograma único :

plot_histogram <- function(df, feature) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)))) +
    geom_histogram(aes(y = ..density..), alpha=0.7, fill="#33AADE", color="black") +
    geom_density(alpha=0.3, fill="red") +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    print(plt)
}

Histograma múltiplo :

plot_multi_histogram <- function(df, feature, label_column) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)), fill=eval(parse(text=label_column)))) +
    geom_histogram(alpha=0.7, position="identity", aes(y = ..density..), color="black") +
    geom_density(alpha=0.7) +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    plt + guides(fill=guide_legend(title=label_column))
}

Uso :

Basta passar seu quadro de dados para as funções acima, juntamente com os argumentos desejados:

plot_histogram(iris, 'Sepal.Width')

insira a descrição da imagem aqui

plot_multi_histogram(iris, 'Sepal.Width', 'Species')

insira a descrição da imagem aqui

O parâmetro extra no plot_multi_histogram é o nome da coluna que contém os rótulos da categoria.

Podemos ver isso de forma mais dramática criando um quadro de dados com muitos meios de distribuição diferentes :

a <-data.frame(n=rnorm(1000, mean = 1), category=rep('A', 1000))
b <-data.frame(n=rnorm(1000, mean = 2), category=rep('B', 1000))
c <-data.frame(n=rnorm(1000, mean = 3), category=rep('C', 1000))
d <-data.frame(n=rnorm(1000, mean = 4), category=rep('D', 1000))
e <-data.frame(n=rnorm(1000, mean = 5), category=rep('E', 1000))
f <-data.frame(n=rnorm(1000, mean = 6), category=rep('F', 1000))
many_distros <- do.call('rbind', list(a,b,c,d,e,f))

Passando o quadro de dados como antes (e ampliando o gráfico usando as opções):

options(repr.plot.width = 20, repr.plot.height = 8)
plot_multi_histogram(many_distros, 'n', 'category')

insira a descrição da imagem aqui


1
Isso é muito útil, espero que receba mais atenção.
Edward Tyler

2
@EdwardTyler Muito verdadeiro. Eu gostaria de poder votar isso mais de uma vez!
ayePete
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.