【问题标题】:Issue with ggplot2, geom_bar, and position="dodge": stacked has correct y values, dodged does notggplot2、geom_bar 和 position="dodge" 的问题:stacked 具有正确的 y 值,dodged 没有
【发布时间】:2012-07-21 04:32:45
【问题描述】:

我有很多时间了解geom_bar()position="dodge"。我试图制作一些条形图来说明两组。最初,数据来自两个单独的数据帧。根据this question,我将我的数据以长格式放置。我的例子:

test <- data.frame(names=rep(c("A","B","C"), 5), values=1:15)
test2 <- data.frame(names=c("A","B","C"), values=5:7)

df <- data.frame(names=c(paste(test$names), paste(test2$names)), num=c(rep(1, 
nrow(test)), rep(2, nrow(test2))), values=c(test$values, test2$values))

我使用该示例是因为它类似于支出与预算示例。每个names 因子级别的支出有很多行,而预算只有一个(每个类别一个预算金额)。

对于堆积条形图,这很好用:

ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) +
geom_bar(stat="identity")

特别要注意 y 值的最大值。它们是来自test 的数据与顶部蓝色显示的test2 值的总和。

根据我读过的其他问题,我只需添加 position="dodge" 以使其成为并排图与堆叠图:

ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
geom_bar(stat="identity", position="dodge")

看起来不错,但请注意新的最大 y 值。似乎它只是从test 的每个名称因子级别中获取最大 y 值作为 y 值。它不再对它们求和。

根据其他一些问题(如this onethis one,我还尝试添加group= 选项但没有成功(产生与上述相同的躲避图):

ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(num))) +
geom_bar(stat="identity", position="dodge")

我不明白为什么堆叠的效果很好,而躲避的不只是将它们并排而不是放在上面。


预计到达时间:我在 ggplot google 群组上找到了一个 recent question,并建议添加 alpha=0.5 以查看发生了什么。并不是 ggplot 从每个分组中获取最大值;它实际上是在每个值的顶部绘制条形图。

似乎在使用position="dodge" 时,ggplot 预计每个 x 只需要一个 y。我联系了 ggplot 开发人员 Winston Chang 以确认并询问是否可以更改,因为我没有看到优势。

似乎stat="identity" 应该告诉 ggplot 计算在 aes() 内部传递的 y=val 而不是在没有 stat="identity" 和不传递 y 值时发生的单个计数。

目前,解决方法似乎是(对于上面的原始 df)进行聚合,因此每个 x 只有一个 y:

df2 <- aggregate(df$values, by=list(df$names, df$num), FUN=sum)
p <- ggplot(df2, aes(x=Group.1, y=x, fill=factor(Group.2)))
p <- p + geom_bar(stat="identity", position="dodge")
p

【问题讨论】:

    标签: r plot ggplot2


    【解决方案1】:

    我认为问题在于您想在num 组的值 堆叠,并在num 的值之间躲避。 查看向条形添加轮廓时会发生什么可能会有所帮助。

    library(ggplot2)
    set.seed(123)
    df <- data.frame(
      id     = 1:18,
      names  = rep(LETTERS[1:3], 6),
      num    = c(rep(1, 15), rep(2, 3)),
      values = sample(1:10, 18, replace=TRUE)
    )
    

    默认情况下,有很多条堆叠在一起——除非你有一个轮廓,否则你只是看不到它们是分开的:

    # Stacked bars
    ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
      geom_bar(stat="identity", colour="black")
    

    如果你躲避,你会得到在 num 的值之间躲避的柱,但在 num 的每个值中可能有多个柱:

    # Dodged on 'num', but some overplotted bars
    ggplot(df, aes(x=factor(names), y=values, fill=factor(num))) + 
      geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1)
    

    如果您还添加id 作为分组变量,它会避开所有这些:

    # Dodging with unique 'id' as the grouping var
    ggplot(df, aes(x=factor(names), y=values, fill=factor(num), group=factor(id))) + 
      geom_bar(stat="identity", colour="black", position="dodge", alpha=0.1)
    

    我认为你想要的是躲避和堆叠,但你不能同时做。 所以最好自己总结数据。

    library(plyr)
    df2 <- ddply(df, c("names", "num"), summarise, values = sum(values))
    
    ggplot(df2, aes(x=factor(names), y=values, fill=factor(num))) + 
      geom_bar(stat="identity", colour="black", position="dodge")
    

    【讨论】:

    • 知道了。指出我实际上是在要求躲避和堆叠,这对您很有帮助。一个小问题:当不使用stat="identity"(所以基本上是制作直方图)时,ggplot 不是“堆叠”个人计数,同时在其他一些特征之间躲避吗?即便如此,我对它目前的工作方式表示同意。我以为我的代码做错了!
    • geom_bar 可能有点令人困惑,因为它用于两个不同的目的:有时它用于绘制您提供的 y 值,有时它会计算每个案例的数量并使用该数量作为 y 值(使用stat="bin")。后一种行为是默认行为(您可以通过 ggplot(df, aes(x=factor(names), fill=factor(num))) + geom_bar(colour="black") 看到它)。在这种情况下,“堆叠”并不完全相同——它是一个汇总stat,而通常的堆叠是一个位置调整。这些事情发生在 ggplot 管道的不同阶段。
    • 感谢您的解释。聚合不是什么大问题,现在我知道我需要这样做,这是从困惑中迈出的一大步:)
    猜你喜欢
    • 2012-06-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2017-09-12
    • 1970-01-01
    相关资源
    最近更新 更多