【问题标题】:ggplot2 - Multi-group histogram with in-group proportions rather than frequencyggplot2 - 具有组内比例而不是频率的多组直方图
【发布时间】:2013-06-28 15:22:10
【问题描述】:

我有三个由ExperimentCohort 因素确定的学生群组。对于每个学生,我都有一个LetterGrade,这也是一个因素。我想为每个ExperimentCohort 绘制一个类似直方图的条形图LetterGrade。使用

ggplot(df, alpha = 0.2, 
       aes(x = LetterGrade, group = ExperimentCohort, fill = ExperimentCohort))                                                                                                                                                       
  + geom_bar(position = "dodge")

让我非常接近,但三个ExperimentCohorts 的学生人数不同。为了在更均匀的领域比较这些,我希望 y 轴是每个字母等级的队列内比例。到目前为止,在绘制之前没有计算这个比例并将它放在一个单独的数据框中,我还没有找到一种方法来做到这一点。

关于 SO 和其他地方的类似问题的每个解决方案都涉及aes(y = ..count../sum(..count..)),但 sum(..count..) 是在整个数据帧中执行的,而不是在每个队列中执行的。有人有建议吗?这是创建示例数据框的代码:

df <- data.frame(ID = 1:60, 
        LetterGrade = sample(c("A", "B", "C", "D", "E", "F"), 60, replace = T),
        ExperimentCohort = sample(c("One", "Two", "Three"), 60, replace = T))

谢谢。

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    错误的解决方案

    您可以使用stat_bin()y=..density.. 获取每个组的百分比。

    ggplot(df, alpha = 0.2,
          aes(x = LetterGrade, group = ExperimentCohort, fill = ExperimentCohort))+
          stat_bin(aes(y=..density..), position='dodge')
    

    更新 - 正确的解决方案

    正如@rpierce 所指出的,y=..density.. 将计算每组的密度值而不是百分比(它们不一样)。

    要获得正确的百分比解决方案,一种方法是在绘图之前计算它们。对于这个使用的函数ddply(),来自库plyr。在每个ExperimentCohort 中使用函数prop.table()table() 计算比例并将它们保存为prop。用names()table() 回复LetterGrade

    df.new<-ddply(df,.(ExperimentCohort),summarise,
                  prop=prop.table(table(LetterGrade)),
                  LetterGrade=names(table(LetterGrade)))
    
     head(df.new)
      ExperimentCohort       prop LetterGrade
    1              One 0.21739130           A
    2              One 0.08695652           B
    3              One 0.13043478           C
    4              One 0.13043478           D
    5              One 0.30434783           E
    6              One 0.13043478           F
    

    现在使用这个新的数据框进行绘图。由于已经计算了比例 - 将它们提供为 y 值并在 geom_bar 中添加 stat="identity"

    ggplot(df.new,aes(LetterGrade,prop,fill=ExperimentCohort))+
      geom_bar(stat="identity",position='dodge')
    

    【讨论】:

    • 成功了。非常感谢...不知道我是如何在其他地方找不到这个答案的。你知道..count.. 的行为方式是什么,而..density.. 没有吗?或者可能是 geom_barstat_bin 之间的差异所特有的?
    • stat_bin 函数分别应用于每个组
    • 除非这个答案不太正确:stats.stackexchange.com/questions/4220/…。请参阅:stackoverflow.com/questions/17655648/… 以获得正确的解决方案。
    • @rpierce 更正了我的答案。
    • (+1) 我最近尝试了这个,并且大部分都回家了,但是需要将这个 prop=prop.table(table(LetterGrade)) 包装在对 as.numeric 的调用中,所以,prop=as.numeric(prop.table(table(LetterGrade)))
    【解决方案2】:

    您也可以通过创建每个组的总和为 1 的 weight 列来做到这一点:

    ggplot(df %>%
             group_by(ExperimentCohort) %>%
             mutate(weight = 1 / n()),
           aes(x = LetterGrade, fill = ExperimentCohort)) +
      geom_histogram(aes(weight = weight), stat = 'count', position = 'dodge')
    

    【讨论】:

    • 对我来说,stat="count" 代码与stat_count 产生了一些问题。删除它会起作用。
    【解决方案3】:

    我最近尝试过此操作并收到调用 ddply 的错误:Column prop must be length 1 (a summary value), not 6。在 ddply 上花了一些时间,但无法完全让解决方案发挥作用,所以我提供了一个替代方案(请注意,这仍然使用 plyr):

    df.new <- df2 %>% 
        group_by(ExperimentCohort,LetterGrade) %>% 
        summarise (n = n()) %>%
        mutate(freq = n / sum(n))
    

    然后你可以像@didzis-elferts 提到的那样绘制它:

    ggplot(df.new,aes(LetterGrade,freq,fill=ExperimentCohort))+
        geom_bar(stat="identity",position='dodge')
    

    【讨论】:

    • 你能解释一下变异步骤吗?为什么 sum(n) 只在实验队列中。我本来希望 sum(n) 用于整个数据帧 - 看起来很神奇!
    • 如果我们希望在整个数据帧上计算 sum(n),我们需要在 mutate 调用之前在管道内调用 ungroup()。请注意,您可以使用 grouping(df.new) 检查分组,并且 summarise 调用将“取消分组”最后一个分组变量。
    • 例如,在数据框中添加一列:df &lt;- data.frame(ID = 1:60,LetterGrade = sample(c("A", "B", "C", "D", "E", "F"), 60, replace = T),ExperimentCohort = sample(c("One", "Two", "Three"), 60, replace = T), test = sample(c("A", "B", "C", "D", "E", "F"), 60, replace = T)) 然后比较来自:df %&gt;% group_by(ExperimentCohort,LetterGrade,test) %&gt;% summarise (n = n()) %&gt;% group_vars() 的输出与:df %&gt;% group_by(ExperimentCohort,LetterGrade,test) %&gt;% group_vars()
    • 这就是为什么mutate(freq = n / sum(n)) 计算 ExperimentCohort 组的总和,而不是 LetterGrade 组的总和。希望这有助于清除它!
    猜你喜欢
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多