R'de iki histogram birlikte nasıl çizilir?


221

R kullanıyorum ve iki veri çerçevem ​​var: havuç ve salatalık. Her veri çerçevesi, ölçülen tüm havuçların (toplam: 100k havuç) ve salatalıkların (toplam: 50k salatalık) uzunluğunu listeleyen tek bir sayısal sütuna sahiptir.

İki histogramı - havuç uzunluğu ve salatalık uzunlukları - aynı arsa üzerine çizmek istiyorum. Örtüşüyorlar, sanırım şeffaflığa da ihtiyacım var. Ayrıca, her gruptaki örnek sayısı farklı olduğu için mutlak sayılar değil göreceli frekanslar kullanmam gerekir.

böyle bir şey güzel olurdu ama iki tablomdan nasıl oluşturulacağını anlamıyorum:

örtüşen yoğunluk


Btw, hangi yazılımı kullanmayı planlıyorsunuz? Açık kaynak için gnuplot.info [gnuplot] ' ı tavsiye ederim . Belgelerinde, istediğinizi yapmak için belirli teknik ve örnek komut dosyaları bulacağınıza inanıyorum.
noel aye

1
Etiketin önerdiği gibi R kullanıyorum (bunu netleştirmek için düzenlenmiş gönderi)
David B

1
Birisi bu iş parçacığında bunu yapmak için bazı kod parçacıkları gönderdi: stackoverflow.com/questions/3485456/…
nico

Yanıtlar:


194

Bağlandığınız görüntü histogramlar için değil yoğunluk eğrileri içindi.

Eğer ggplot üzerinde okuyorsanız, belki de eksik olan tek şey iki veri çerçevenizi uzun bir çerçevede birleştirmektir.

Öyleyse, sahip olduğunuz gibi bir şeyle başlayalım, iki ayrı veri kümesi ve bunları birleştirin.

carrots <- data.frame(length = rnorm(100000, 6, 2))
cukes <- data.frame(length = rnorm(50000, 7, 2.5))

# Now, combine your two dataframes into one.  
# First make a new column in each that will be 
# a variable to identify where they came from later.
carrots$veg <- 'carrot'
cukes$veg <- 'cuke'

# and combine into your new data frame vegLengths
vegLengths <- rbind(carrots, cukes)

Bundan sonra, verileriniz zaten uzun formattaysa gereksizdir, planınızı yapmak için sadece bir satıra ihtiyacınız vardır.

ggplot(vegLengths, aes(length, fill = veg)) + geom_density(alpha = 0.2)

resim açıklamasını buraya girin

Şimdi, eğer histogramları gerçekten istiyorsanız, aşağıdakiler işe yarayacaktır. Varsayılan "yığın" bağımsız değişkeninden konumu değiştirmeniz gerektiğini unutmayın. Verilerinizin nasıl görünmesi gerektiği hakkında bir fikriniz yoksa bunu kaçırabilirsiniz. Daha yüksek bir alfa daha iyi görünüyor. Ayrıca yoğunluk histogramları yaptığımı da unutmayın. y = ..density..Saymak için geri almak kolaydır .

ggplot(vegLengths, aes(length, fill = veg)) + 
   geom_histogram(alpha = 0.5, aes(y = ..density..), position = 'identity')

resim açıklamasını buraya girin


8
Histogramlarla kalmak istiyorsanız, kullanın ggplot(vegLengths, aes(length, fill = veg)) + geom_bar(pos="dodge"). Bu MATLAB'da olduğu gibi titreşimli histogramlar yapar.
mbq

1
Cevap için teşekkürler! 'Position = "identity"' kısmı aslında önemlidir çünkü aksi takdirde çubuklar istiflenir, bu da varsayılan olarak "kimlik" gibi görünen bir yoğunlukla birleştirildiğinde yanıltıcıdır, yani yığılma yerine üst üste bindirilir.
Gölge

265

Temel grafikleri ve alfa harmanlamayı (tüm grafik cihazlarında çalışmayan) kullanan daha da basit bir çözüm:

set.seed(42)
p1 <- hist(rnorm(500,4))                     # centered at 4
p2 <- hist(rnorm(500,6))                     # centered at 6
plot( p1, col=rgb(0,0,1,1/4), xlim=c(0,10))  # first histogram
plot( p2, col=rgb(1,0,0,1/4), xlim=c(0,10), add=T)  # second

Anahtar, renklerin yarı saydam olmasıdır.

Düzenleme, iki yıldan fazla bir süre sonra : Bu sadece bir upvote var, ben de kodun alfa-harmanlama kadar darn yararlı olarak ne ürettiğini bir görsel ekleyebilir rakam anlıyorum:

resim açıklamasını buraya girin


6
+1 hepinize teşekkürler, bu daha pürüzsüz bir gistograma dönüştürülebilir mi ( had.co.nz/ggplot2/graphics/55078149a733dd1a0b42a57faf847036.png gibi )?
David B

3
plotKomutları neden ayırdınız? Tüm bu seçenekleri histkomutlara koyabilir ve sadece iki satırda ikisini kullanabilirsiniz.
John

@John Nasıl yapardın?
HelloWorld

plotDediğim gibi, komuttaki seçenekleri doğrudan hist komutuna koyun . Kodu göndermek, yorumların ne olduğu ile ilgili değildir.
John

44

Burada , çakışan histogramları temsil etmek için sözde saydamlık kullanan yazdığım bir işlev var

plotOverlappingHist <- function(a, b, colors=c("white","gray20","gray50"),
                                breaks=NULL, xlim=NULL, ylim=NULL){

  ahist=NULL
  bhist=NULL

  if(!(is.null(breaks))){
    ahist=hist(a,breaks=breaks,plot=F)
    bhist=hist(b,breaks=breaks,plot=F)
  } else {
    ahist=hist(a,plot=F)
    bhist=hist(b,plot=F)

    dist = ahist$breaks[2]-ahist$breaks[1]
    breaks = seq(min(ahist$breaks,bhist$breaks),max(ahist$breaks,bhist$breaks),dist)

    ahist=hist(a,breaks=breaks,plot=F)
    bhist=hist(b,breaks=breaks,plot=F)
  }

  if(is.null(xlim)){
    xlim = c(min(ahist$breaks,bhist$breaks),max(ahist$breaks,bhist$breaks))
  }

  if(is.null(ylim)){
    ylim = c(0,max(ahist$counts,bhist$counts))
  }

  overlap = ahist
  for(i in 1:length(overlap$counts)){
    if(ahist$counts[i] > 0 & bhist$counts[i] > 0){
      overlap$counts[i] = min(ahist$counts[i],bhist$counts[i])
    } else {
      overlap$counts[i] = 0
    }
  }

  plot(ahist, xlim=xlim, ylim=ylim, col=colors[1])
  plot(bhist, xlim=xlim, ylim=ylim, col=colors[2], add=T)
  plot(overlap, xlim=xlim, ylim=ylim, col=colors[3], add=T)
}

İşte R'nin saydam renkler desteğini kullanarak yapmanın başka bir yolu

a=rnorm(1000, 3, 1)
b=rnorm(1000, 6, 1)
hist(a, xlim=c(0,10), col="red")
hist(b, add=T, col=rgb(0, 1, 0, 0.5) )

Sonuçlar böyle bir şeye benziyor: alternatif metin


Tüm grafik cihazlarında kullanılabilen bir seçenek için +1 (ör. postscript)
Lenna

31

Zaten güzel cevaplar var, ama bunu eklemeyi düşündüm. Bana iyi görünüyor. (@Dirk'ten rastgele sayılar kopyalandı). library(scales)gerekli`

set.seed(42)
hist(rnorm(500,4),xlim=c(0,10),col='skyblue',border=F)
hist(rnorm(500,6),add=T,col=scales::alpha('red',.5),border=F)

Sonuç ...

resim açıklamasını buraya girin

Güncelleme: Bu örtüşen fonksiyon bazıları için de yararlı olabilir.

hist0 <- function(...,col='skyblue',border=T) hist(...,col=col,border=border) 

I sonucu hissetmek hist0daha bakmak güzel olduğunuhist

hist2 <- function(var1, var2,name1='',name2='',
              breaks = min(max(length(var1), length(var2)),20), 
              main0 = "", alpha0 = 0.5,grey=0,border=F,...) {    

library(scales)
  colh <- c(rgb(0, 1, 0, alpha0), rgb(1, 0, 0, alpha0))
  if(grey) colh <- c(alpha(grey(0.1,alpha0)), alpha(grey(0.9,alpha0)))

  max0 = max(var1, var2)
  min0 = min(var1, var2)

  den1_max <- hist(var1, breaks = breaks, plot = F)$density %>% max
  den2_max <- hist(var2, breaks = breaks, plot = F)$density %>% max
  den_max <- max(den2_max, den1_max)*1.2
  var1 %>% hist0(xlim = c(min0 , max0) , breaks = breaks,
                 freq = F, col = colh[1], ylim = c(0, den_max), main = main0,border=border,...)
  var2 %>% hist0(xlim = c(min0 , max0),  breaks = breaks,
                 freq = F, col = colh[2], ylim = c(0, den_max), add = T,border=border,...)
  legend(min0,den_max, legend = c(
    ifelse(nchar(name1)==0,substitute(var1) %>% deparse,name1),
    ifelse(nchar(name2)==0,substitute(var2) %>% deparse,name2),
    "Overlap"), fill = c('white','white', colh[1]), bty = "n", cex=1,ncol=3)

  legend(min0,den_max, legend = c(
    ifelse(nchar(name1)==0,substitute(var1) %>% deparse,name1),
    ifelse(nchar(name2)==0,substitute(var2) %>% deparse,name2),
    "Overlap"), fill = c(colh, colh[2]), bty = "n", cex=1,ncol=3) }

Sonucu

par(mar=c(3, 4, 3, 2) + 0.1) 
set.seed(100) 
hist2(rnorm(10000,2),rnorm(10000,3),breaks = 50)

dır-dir

resim açıklamasını buraya girin


24

"Klasik" R grafiklerinde bunu nasıl yapabileceğinize bir örnek:

## generate some random data
carrotLengths <- rnorm(1000,15,5)
cucumberLengths <- rnorm(200,20,7)
## calculate the histograms - don't plot yet
histCarrot <- hist(carrotLengths,plot = FALSE)
histCucumber <- hist(cucumberLengths,plot = FALSE)
## calculate the range of the graph
xlim <- range(histCucumber$breaks,histCarrot$breaks)
ylim <- range(0,histCucumber$density,
              histCarrot$density)
## plot the first graph
plot(histCarrot,xlim = xlim, ylim = ylim,
     col = rgb(1,0,0,0.4),xlab = 'Lengths',
     freq = FALSE, ## relative, not absolute frequency
     main = 'Distribution of carrots and cucumbers')
## plot the second graph on top of this
opar <- par(new = FALSE)
plot(histCucumber,xlim = xlim, ylim = ylim,
     xaxt = 'n', yaxt = 'n', ## don't add axes
     col = rgb(0,0,1,0.4), add = TRUE,
     freq = FALSE) ## relative, not absolute frequency
## add a legend in the corner
legend('topleft',c('Carrots','Cucumbers'),
       fill = rgb(1:0,0,0:1,0.4), bty = 'n',
       border = NA)
par(opar)

Bununla ilgili tek sorun, histogram kesilmelerinin hizalanması durumunda daha iyi görünmesidir, bu da manuel olarak yapılması gerekebilir (iletilen argümanlarda hist).


Çok hoş. Ayrıca bana şunu hatırlattı stackoverflow.com/questions/3485456/…
George Dontas

Bunu cevaplamak, çünkü bu cevap, ggplotiki histogramınızın büyük ölçüde farklı örnek boyutlarına sahip olup olmadığını doğrudan açıklayan tek cevaptır (içinde olanlar dışında ).
MichaelChirico

Bu yöntemi beğendim, molaları seq () ile tanımlayarak senkronize edebileceğinizi unutmayın. Örneğin:breaks=seq(min(data$some_property), max(data$some_property), by=(max_prop - min_prop)/20)
Deruijter

17

İşte sadece R üssünde verdiğim ggplot2 sürümü gibi @nullglob'dan bazılarını kopyaladım.

veriyi üret

carrots <- rnorm(100000,5,2)
cukes <- rnorm(50000,7,2.5)

Bunu ggplot2 gibi bir veri çerçevesine koymanıza gerek yoktur. Bu yöntemin dezavantajı, çizimin ayrıntılarını çok daha fazla yazmanız gerektiğidir. Avantajı, arsa hakkında daha fazla ayrıntı üzerinde kontrol sahibi olmanızdır.

## calculate the density - don't plot yet
densCarrot <- density(carrots)
densCuke <- density(cukes)
## calculate the range of the graph
xlim <- range(densCuke$x,densCarrot$x)
ylim <- range(0,densCuke$y, densCarrot$y)
#pick the colours
carrotCol <- rgb(1,0,0,0.2)
cukeCol <- rgb(0,0,1,0.2)
## plot the carrots and set up most of the plot parameters
plot(densCarrot, xlim = xlim, ylim = ylim, xlab = 'Lengths',
     main = 'Distribution of carrots and cucumbers', 
     panel.first = grid())
#put our density plots in
polygon(densCarrot, density = -1, col = carrotCol)
polygon(densCuke, density = -1, col = cukeCol)
## add a legend in the corner
legend('topleft',c('Carrots','Cucumbers'),
       fill = c(carrotCol, cukeCol), bty = 'n',
       border = NA)

resim açıklamasını buraya girin


9

@Dirk Eddelbuettel: Temel fikir mükemmel ama gösterilen kod geliştirilebilir. [Açıklamak çok zaman alıyor, dolayısıyla ayrı bir cevap ve bir yorum değil.]

hist()Eklemek gerekir böylece varsayılan olarak işlev, araziler çizer plot=FALSEseçeneği. Ayrıca, plot(0,0,type="n",...)eksen etiketlerini, çizim başlığını vb. Ekleyebileceğiniz bir çağrı ile çizim alanını oluşturmak daha nettir . Son olarak, birinin iki histogramı ayırt etmek için gölgeleme de kullanabileceğini belirtmek isterim. İşte kod:

set.seed(42)
p1 <- hist(rnorm(500,4),plot=FALSE)
p2 <- hist(rnorm(500,6),plot=FALSE)
plot(0,0,type="n",xlim=c(0,10),ylim=c(0,100),xlab="x",ylab="freq",main="Two histograms")
plot(p1,col="green",density=10,angle=135,add=TRUE)
plot(p2,col="blue",density=10,angle=45,add=TRUE)

Ve işte sonuç (RStudio nedeniyle biraz fazla geniş :-)):

resim açıklamasını buraya girin


Bunu temel alır ve postscriptcihazlarda uygulanabilir ve taban kullanarak çok basit bir seçenektir .
MichaelChirico

6

Plotly'nin R API'sı sizin için yararlı olabilir. Aşağıdaki grafik burada .

library(plotly)
#add username and key
p <- plotly(username="Username", key="API_KEY")
#generate data
x0 = rnorm(500)
x1 = rnorm(500)+1
#arrange your graph
data0 = list(x=x0,
         name = "Carrots",
         type='histogramx',
         opacity = 0.8)

data1 = list(x=x1,
         name = "Cukes",
         type='histogramx',
         opacity = 0.8)
#specify type as 'overlay'
layout <- list(barmode='overlay',
               plot_bgcolor = 'rgba(249,249,251,.85)')  
#format response, and use 'browseURL' to open graph tab in your browser.
response = p$plotly(data0, data1, kwargs=list(layout=layout))

url = response$url
filename = response$filename

browseURL(response$url)

Tam açıklama: Ben takımdayım.

grafik


1

O kadar çok harika cevap ama bir fonksiyon yazdım kiplotMultipleHistograms() ) işlevi , başka bir cevap ekleyeceğimi düşündüm.

Bu işlevin avantajı, uygun X ve Y ekseni sınırlarını otomatik olarak ayarlaması ve tüm dağıtımlarda kullandığı yaygın bir grup kümesini tanımlamasıdır.

Bunu nasıl kullanacağınız aşağıda açıklanmıştır:

# Install the plotteR package
install.packages("devtools")
devtools::install_github("JosephCrispell/basicPlotteR")
library(basicPlotteR)

# Set the seed
set.seed(254534)

# Create random samples from a normal distribution
distributions <- list(rnorm(500, mean=5, sd=0.5), 
                      rnorm(500, mean=8, sd=5), 
                      rnorm(500, mean=20, sd=2))

# Plot overlapping histograms
plotMultipleHistograms(distributions, nBins=20, 
                       colours=c(rgb(1,0,0, 0.5), rgb(0,0,1, 0.5), rgb(0,1,0, 0.5)), 
                       las=1, main="Samples from normal distribution", xlab="Value")

resim açıklamasını buraya girin

plotMultipleHistograms()Fonksiyon dağılımları herhangi bir sayıda alabilir ve tüm genel çizim parametreleri onunla çalışması gerekir (örneğin: las, mainvs.).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.