【问题标题】:Overlaying histograms with ggplot2 in R在 R 中用 ggplot2 覆盖直方图
【发布时间】:2011-10-20 21:58:28
【问题描述】:

我是 R 新手,正在尝试将 3 个直方图绘制到同一张图上。 一切正常,但我的问题是您看不到 2 个直方图重叠的位置 - 它们看起来相当截断。

当我制作密度图时,它看起来很完美:每条曲线都被黑色框线包围,曲线重叠的地方颜色看起来不同。

有人可以告诉我是否可以使用第一张图片中的直方图实现类似的效果?这是我正在使用的代码:

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)

【问题讨论】:

  • 直方图和密度图的超链接坏了

标签: r ggplot2


【解决方案1】:

您当前的代码:

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

告诉ggplot 使用f0 中的所有值构造一个 直方图,然后根据变量utt 为这个直方图的条形着色。

您想要的是创建三个独立的直方图,并使用 alpha 混合,以便它们彼此可见。因此,您可能希望对geom_histogram 使用三个单独的调用,每个调用都有自己的数据框并填充:

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

这是一个带有一些输出的具体示例:

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)

产生这样的东西:

编辑以修正错别字;你想要填充,而不是颜色。

【讨论】:

  • 当子集的大小不同时,这不起作用。知道如何解决这个问题吗? (例如,在“a”上使用 100 分,在“b”上使用 50 分的数据)。
  • 这种方法的一个缺点是我很难让它显示一个图例(尽管这可能只是由于我缺乏知识)。 @kohske 下面的另一个答案将默认显示一个图例,然后可以修改(以及直方图上显示的特定颜色),例如scale_fill_manual().
  • 没错,我们如何在其中添加图例??
  • @shenglih 对于传奇人物,kohske 下面的回答更好。他的回答通常也更好。
  • f0 是从哪里来的?
【解决方案2】:

使用@joran 的样本数据,

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

注意geom_histogram的默认位置是“stack”。

参见本页“位置调整”:

geom_histogram documentation

【讨论】:

  • 我认为这应该是最佳答案,因为它避免了重复代码
  • position = 'identity' 不仅是一个更易读的答案,它还与更复杂的图更好地融合在一起,例如对aes()aes_string() 的混合调用。
  • 此答案还将自动显示颜色图例,而@joran 的答案不会。然后可以使用例如修改图例scale_fill_manual()。这个函数也可以用来修改直方图中的颜色。
  • 另外,请确保fill 中使用的变量是一个因素。
  • 我个人认为 stackoverflow 应该首先列出最受好评的答案。 “正确答案”仅代表一个人的意见。
【解决方案3】:

虽然在 ggplot2 中绘制多个/重叠直方图只需要几行代码,但结果并不总是令人满意。需要正确使用边框和颜色,以确保眼睛可以区分直方图

以下函数平衡边框颜色、不透明度和叠加密度图,使查看者能够区分分布

单个直方图

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

多重直方图

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

用法

只需将您的数据框传递给上述函数以及所需的参数:

plot_histogram(iris, 'Sepal.Width')

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

plot_multi_histogram 中的额外参数是包含类别标签的列的名称。

我们可以通过创建具有许多不同分布方式的数据框来更显着地看到这一点:

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

像以前一样传递数据框(并使用选项扩大图表):

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

要为每个分布添加单独的垂直线

plot_multi_histogram <- function(df, feature, label_column, means) {
    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(xintercept=means, color="black", linetype="dashed", size=1)
    labs(x=feature, y = "Density")
    plt + guides(fill=guide_legend(title=label_column))
}

与之前的 plot_multi_histogram 函数的唯一变化是在参数中添加了means,并将geom_vline 行更改为接受多个值。

用法

options(repr.plot.width = 20, repr.plot.height = 8)
plot_multi_histogram(many_distros, "n", 'category', c(1, 2, 3, 4, 5, 6))

结果

由于我在many_distros 中明确设置了方法,因此我可以简单地将它们传入。或者,您可以简单地在函数内部计算这些值并使用这种方式。

【讨论】:

  • 这个很有用,希望得到更多关注。
  • @EdwardTyler 非常正确。我希望我能不止一次地对此表示赞同!
  • 这太棒了!我唯一希望改进的是垂直线。如果我们可以为每个分布获得单独的垂直线,那就太好了。
猜你喜欢
  • 2021-09-06
  • 2018-08-02
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多