आर में एक साथ दो हिस्टोग्राम कैसे प्लॉट करें?


221

मैं आर का उपयोग कर रहा हूं और मेरे पास दो डेटा फ़्रेम हैं: गाजर और खीरे। प्रत्येक डेटा फ़्रेम में एक एकल संख्यात्मक स्तंभ होता है जो सभी मापा गाजर (कुल: 100k गाजर) और खीरे की लंबाई को सूचीबद्ध करता है (कुल: 50k खीरे)।

मैं एक ही भूखंड पर दो हिस्टोग्राम - गाजर की लंबाई और खीरे की लंबाई की साजिश करना चाहता हूं। वे ओवरलैप करते हैं, इसलिए मुझे लगता है कि मुझे भी कुछ पारदर्शिता की आवश्यकता है। मुझे भी सापेक्ष आवृत्तियों का उपयोग करने की आवश्यकता है, पूर्ण संख्या नहीं क्योंकि प्रत्येक समूह में उदाहरणों की संख्या अलग-अलग है।

यह कुछ अच्छा होगा, लेकिन मुझे समझ नहीं आ रहा है कि इसे अपनी दो तालिकाओं से कैसे बनाया जाए:

अतिव्याप्त घनत्व


Btw, आप किस सॉफ्टवेयर का उपयोग करने की योजना बना रहे हैं? ओपन सोर्स के लिए, मैं gnuplot.info [gnuplot] की सलाह दूंगा । इसके दस्तावेज़ीकरण में, मुझे विश्वास है कि आप जो चाहते हैं, उसे करने के लिए आपको कुछ निश्चित तकनीक और नमूना स्क्रिप्ट मिलेंगे।
नोएल ऐ

1
मैं आर का उपयोग कर रहा हूं क्योंकि टैग का सुझाव है (संपादित पोस्ट को स्पष्ट करने के लिए)
डेविड बी

1
किसी ने कुछ कोड स्निपेट इस धागे में करने के लिए पोस्ट किया: stackoverflow.com/questions/3485456/…
nico

जवाबों:


194

वह छवि जो आप से जुड़ी थी, घनत्व घटता के लिए थी, हिस्टोग्राम नहीं।

यदि आप ggplot पर पढ़ रहे हैं, तो हो सकता है कि केवल एक चीज जो आपको याद आ रही है, वह आपके दो डेटा फ़्रेमों को एक लंबे समय में संयोजित कर रही हो।

तो, चलो कुछ ऐसा करें जो आपके पास है, दो अलग-अलग डेटा सेट करें और उन्हें संयोजित करें।

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)

उसके बाद, जो अनावश्यक है यदि आपका डेटा पहले से ही लंबे प्रारूप में है, तो आपको अपना प्लॉट बनाने के लिए केवल एक लाइन की आवश्यकता है।

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

यहां छवि विवरण दर्ज करें

अब, यदि आप वास्तव में हिस्टोग्राम चाहते हैं तो निम्नलिखित काम करेगा। ध्यान दें कि आपको डिफ़ॉल्ट "स्टैक" तर्क से स्थिति बदलनी चाहिए। आपको याद हो सकता है कि अगर आपको वास्तव में इस बात का अंदाजा नहीं है कि आपका डेटा कैसा दिखना चाहिए। एक उच्च अल्फा वहां बेहतर दिखता है। यह भी ध्यान दें कि मैंने इसे घनत्व हिस्टोग्राम बनाया है। इसे हटाने के लिए आसान है y = ..density..यह मायने रखता है करने के लिए वापस पाने के लिए।

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

यहां छवि विवरण दर्ज करें


8
यदि आप हिस्टोग्राम के साथ रहना चाहते हैं, तो उपयोग करें ggplot(vegLengths, aes(length, fill = veg)) + geom_bar(pos="dodge")। यह MATLAB की तरह इंटरलेस्ड हिस्टोग्राम बनाएगा।
mbq

1
जवाब के लिए thx! 'स्थिति = "पहचान" "भाग वास्तव में महत्वपूर्ण है क्योंकि अन्यथा सलाखों को स्टैक्ड किया जाता है जो कि एक घनत्व के साथ संयुक्त होने पर भ्रामक होता है जो डिफ़ॉल्ट रूप से" पहचान "लगता है, यानी, स्टैक किए जाने के विपरीत ओवरलेड।
छाया

265

यहाँ आधार ग्राफिक्स और अल्फा-सम्मिश्रण (जो सभी ग्राफिक्स उपकरणों पर काम नहीं करता है) का उपयोग करके एक और भी सरल समाधान है:

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

कुंजी यह है कि रंग अर्ध-पारदर्शी हैं।

संपादित करें, दो साल से अधिक समय के बाद : जैसा कि यह सिर्फ एक उत्थान है, मुझे लगता है कि मैं एक दृश्य जोड़ सकता हूं कि अल्फा-सम्मिश्रण के रूप में कोड क्या पैदा करता है यह कितना उपयोगी है:

यहां छवि विवरण दर्ज करें


6
+1 आप सभी को धन्यवाद, क्या इसे एक स्मूथ जिस्टोग्राम (जैसे has.co.nz/ggplot2/graphics/55078149a733dd1a0b42a57faf847036.png ) में बदला जा सकता है ?
डेविड बी

3
आपने plotआज्ञाओं को अलग क्यों किया ? आप उन सभी विकल्पों को histकमांड में डाल सकते हैं और इसे दो लाइनों में दो कर सकते हैं।
जॉन

@ जॉन आप इसे कैसे करेंगे?
हैलोवर्ल्ड

plotजैसा कि मैंने कहा था कि विकल्पों को सीधे हिस्ट कमांड में डालें । कोड पोस्ट करना वैसा नहीं है, जैसी टिप्पणी के लिए है।
जॉन

44

यहाँ मैंने एक फ़ंक्शन लिखा है जो अतिव्यापी हिस्टोग्राम का प्रतिनिधित्व करने के लिए छद्म पारदर्शिता का उपयोग करता है

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)
}

पारदर्शी रंगों के लिए आर के समर्थन का उपयोग करके इसे करने का एक और तरीका है

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) )

परिणाम कुछ इस तरह दिख रहे हैं: वैकल्पिक शब्द


सभी ग्राफिक्स उपकरणों (जैसे postscript) पर उपलब्ध एक विकल्प के लिए +1
लेनना

31

पहले से ही सुंदर जवाब हैं, लेकिन मैंने इसे जोड़ने के बारे में सोचा। मुझे ठीक लगता है। (@Dirk से यादृच्छिक संख्याओं की प्रतिलिपि बनाई गई)। library(scales)की जरूरत है

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)

परिणाम है...

यहां छवि विवरण दर्ज करें

अद्यतन: यह अतिव्यापी फ़ंक्शन कुछ के लिए भी उपयोगी हो सकता है।

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

मुझे लगता है कि परिणाम hist0देखने में सुंदर हैhist

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) }

का परिणाम

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

है

यहां छवि विवरण दर्ज करें


24

यहाँ एक उदाहरण है कि आप इसे "क्लासिक" आर ग्राफिक्स में कैसे कर सकते हैं:

## 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)

इसके साथ एकमात्र मुद्दा यह है कि हिस्टोग्राम टूटने से जुड़ने पर यह बहुत बेहतर दिखता है, जिसे मैन्युअल रूप से (तर्कों में पारित होने के लिए hist) करना पड़ सकता है ।


बहुत अच्छा। इसने मुझे यह भी याद दिलाया कि एक stackoverflow.com/questions/3485456/…
जॉर्ज डोंटास

इसे छोड़ना क्योंकि यह उत्तर केवल एक है (उन लोगों के अलावा ggplot) जो सीधे खाते हैं कि क्या आपके दो हिस्टोग्राम्स के नमूने अलग-अलग हैं।
माइकलचिरिको

मुझे यह विधि पसंद है, ध्यान दें कि आप सीक () के साथ उन्हें परिभाषित करके ब्रेक को सिंक्रनाइज़ कर सकते हैं। उदाहरण के लिए:breaks=seq(min(data$some_property), max(data$some_property), by=(max_prop - min_prop)/20)
Deruijter

17

यहाँ ggplot2 जैसा संस्करण है जो मैंने केवल बेस आर में दिया था। मैंने @nullglob से कुछ कॉपी किया।

डेटा जनरेट करें

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

आपको इसे ggplot2 की तरह डेटा फ्रेम में रखने की आवश्यकता नहीं है। इस पद्धति का दोष यह है कि आपको भूखंड के विवरण के बारे में अधिक जानकारी लिखनी होगी। लाभ यह है कि आपके पास प्लॉट के अधिक विवरण पर नियंत्रण है।

## 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)

यहां छवि विवरण दर्ज करें


9

@ डर्क एडल्डबुलेट: मूल विचार उत्कृष्ट है लेकिन दिखाए गए कोड को बेहतर बनाया जा सकता है। [समझाने के लिए लंबा समय लेता है, इसलिए एक अलग उत्तर और टिप्पणी नहीं।]

hist()ताकि आप जोड़ने की जरूरत है डिफ़ॉल्ट रूप से समारोह भूखंडों खींचता है, plot=FALSEविकल्प। इसके अलावा, यह एक plot(0,0,type="n",...)कॉल द्वारा प्लॉट क्षेत्र को स्थापित करने के लिए स्पष्ट है जिसमें आप अक्ष लेबल, प्लॉट शीर्षक आदि जोड़ सकते हैं। अंत में, मैं यह उल्लेख करना चाहूंगा कि दोनों हिस्टोग्राम के बीच अंतर करने के लिए छायांकन का उपयोग भी किया जा सकता है। यहाँ कोड है:

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)

और यहाँ परिणाम (RStudio :-) के कारण थोड़ा बहुत चौड़ा है):

यहां छवि विवरण दर्ज करें


इसे ऊपर उठाना क्योंकि यह postscriptउपकरणों पर आधार और व्यवहार्य का उपयोग करते हुए एक बहुत ही सरल विकल्प है।
माइकलचिरिको

6

प्लॉटली का R API आपके लिए उपयोगी हो सकता है। नीचे दिया गया ग्राफ़ यहाँ है

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)

पूरा खुलासा: मैं टीम पर हूं।

ग्राफ़


1

इतने महान जवाब लेकिन जब से मैंने सिर्फ एक फ़ंक्शन लिखा है (plotMultipleHistograms() ) फ़ंक्शन , मैंने सोचा कि मैं एक और जवाब जोड़ूंगा।

इस फ़ंक्शन का लाभ यह है कि यह स्वचालित रूप से उपयुक्त एक्स और वाई अक्ष सीमा निर्धारित करता है और सभी वितरण में उपयोग किए जाने वाले डिब्बे के एक सामान्य सेट को परिभाषित करता है।

इसका उपयोग कैसे करें:

# 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")

यहां छवि विवरण दर्ज करें

plotMultipleHistograms()समारोह वितरण के किसी भी संख्या ले जा सकते हैं, और सभी सामान्य की साजिश रचने मापदंडों इसके साथ काम करना चाहिए (उदाहरण के लिए: las, main, आदि)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.