r r语言直方图 - 如何在R中一起绘制两个直方图?




4 Answers

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

如果你一直在阅读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)

现在,如果你真的想要直方图,以下将起作用。 请注意,您必须从默认的“堆栈”参数中更改位置。 如果你不确定你的数据应该是什么样子的话,你可能会错过。 那里的Alpha看起来更好。 另外请注意,我已经制作了密度直方图。 很容易去除y = ..density..以使其恢复计数。

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

ggplot直方图 r语言geom_histogram

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

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

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




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

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

结果看起来像这样:




已经有了美丽的答案,但我想添加这个。 在我看来很好。 (从@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)




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

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




Related