如何在R中绘制两个直方图?

我使用R和我有两个数据框架:胡萝卜和黄瓜。 每个数据框都有一个数字列,列出所有测量的胡萝卜(总数:10万个胡萝卜)和黄瓜(总数:5万个黄瓜)的长度。

我想绘制两个直方图 – 胡萝卜长度和黄瓜长度 – 在同一个阴谋。 他们重叠,所以我想我也需要一些透明度。 我也需要使用相对频率而不是绝对数,因为每个组中的实例数是不同的。

这样的事情会很好,但我不明白如何从我的两个表创build它:

重叠密度

你链接到的图像是密度曲线,而不是直方图。

如果你一直在阅读ggplot,那么你可能唯一缺less的就是把你的两个数据框合并成一个长的数据框。

所以,让我们从你所拥有的东西开始,两个独立的数据集合在一起。

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) 

在这里输入图像描述

现在,如果你真的想要直方图,以下将工作。 请注意,您必须从默认的“堆栈”参数改变位置。 如果你不知道你的数据应该是什么样子的话,你可能会错过。 更高的alpha看起来更好。 还要注意我做了密度直方图。 很容易去除y = ..density..以使其重新计数。

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

在这里输入图像描述

这是一个更简单的解决scheme,使用基础graphics和alpha混合(不适用于所有graphics设备):

 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 

关键是颜色是半透明的。

编辑,超过两年后 :因为这只是一个upvote,我想我可以添加一个代码生成的视觉alpha混合是非常有用的:

在这里输入图像描述

这是我写的一个函数,它使用伪透明度来表示重叠的直方图

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

这是另一种使用R支持透明颜色的方法

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

结果最终看起来像这样: 替代文字

下面是一个如何在“经典”Rgraphics中做到这一点的例子:

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

唯一的问题是,如果直方图中断是alignment的,那么看起来好多了,这可能需要手动完成(在传递给hist的参数中)。

已经有美丽的答案,但我想join这个。 看起来不错。 (从@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) 

结果是…

在这里输入图像描述

更新:这个重叠的function也可能对一些有用的。

 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) 

在这里输入图像描述

这里的版本就像ggplot2,我只是在基地R.我从@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) 

在这里输入图像描述

@Dirk Eddelbuettel:基本思想非常好,但是所显示的代码可以改进。 [需要很长时间来解释,因此是一个单独的答案,而不是一个评论。]

hist()函数默认绘制graphics,所以你需要添加plot=FALSE选项。 此外,通过一个plot(0,0,type="n",...)调用来创build绘图区域更加清晰,您可以在其中添加轴标签,绘图标题等。最后,我想提到也可以使用阴影区分两个直方图。 这里是代码:

 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 :-)有点太宽):

在这里输入图像描述

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

充分披露:我在队里。

图形