ggplot2 - 具有组内比例而非频率的多组直方图

时间:2013-06-28 15:22:11

标签: r ggplot2

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

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

感谢。

3 个答案:

答案 0 :(得分:19)

错误的解决方案

您可以使用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。在使用函数ExperimentCohortprop.table()的每个table()计算比例中,将其保存为propnames()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值提供,并在stat="identity"内添加geom_bar

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

enter image description here

答案 1 :(得分:5)

您也可以通过为每个组创建一个总计为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')

答案 2 :(得分:1)

我最近尝试过此操作,并在调用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')