【问题标题】:Let ggplot2 histogram show classwise percentages on y axis让 ggplot2 直方图在 y 轴上显示分类百分比
【发布时间】:2015-07-03 06:44:16
【问题描述】:
library(ggplot2)
data = diamonds[, c('carat', 'color')]
data = data[data$color %in% c('D', 'E'), ]

我想比较颜色 D 和 E 的克拉直方图,并在 y 轴上使用分类百分比。我尝试过的解决方案如下:

解决方案 1:

ggplot(data=data, aes(carat, fill=color)) +  geom_bar(aes(y=..density..), position='dodge', binwidth = 0.5) + ylab("Percentage") +xlab("Carat")

这不太正确,因为 y 轴显示了估计密度的高度。

解决方案2:

 ggplot(data=data, aes(carat, fill=color)) +  geom_histogram(aes(y=(..count..)/sum(..count..)), position='dodge', binwidth = 0.5) + ylab("Percentage") +xlab("Carat")

这也不是我想要的,因为在y轴上用来计算比率的分母是D+E的总数。

有没有办法用 ggplot2 的堆叠直方图显示分类百分比?也就是说,不是在 y 轴上显示 (# of obs in bin)/count(D+E),我希望它显示 (# of obs in bin)/count(D) 和 (# of obs in bin) /count(E) 分别用于两个颜色类别。谢谢。

【问题讨论】:

  • 您是否考虑过在 ggplot 之外汇总您的数据?

标签: r ggplot2


【解决方案1】:

您可以使用..group.. 特殊变量对..count.. 向量进行子集化,从而按组对它们进行缩放。由于所有的点,它很丑陋,但它就在这里

ggplot(data, aes(carat, fill=color)) +
  geom_histogram(aes(y=c(..count..[..group..==1]/sum(..count..[..group..==1]),
                         ..count..[..group..==2]/sum(..count..[..group..==2]))*100),
                 position='dodge', binwidth=0.5) +
  ylab("Percentage") + xlab("Carat")

【讨论】:

  • 而不是将aes y 向量缩放100,您只需添加scale_y_continuous(labels = percent)
  • Hrrrm,有没有什么地方可以读到关于“..count..”和“..group..”特殊变量以及它们如何工作的信息?我不太明白程序如何理解如何将组号与颜色联系起来!
  • @Magnus 自从我查看细节以来已经有一段时间了,但 IIRC ..<var>.. 对应于 ggplot_build(ggplot(data, ...))$data 中的列。 aes 做了一堆元数据来转换变量名
【解决方案2】:

似乎在 ggplot2 之外对数据进行分箱是可行的方法。但我仍然很想看看是否有办法用 ggplot2 来做。

library(dplyr)
breaks = seq(0,4,0.5)

data$carat_cut = cut(data$carat, breaks = breaks)

data_cut = data %>%
  group_by(color, carat_cut) %>%
  summarise (n = n()) %>%
  mutate(freq = n / sum(n))

ggplot(data=data_cut, aes(x = carat_cut, y=freq*100, fill=color)) + geom_bar(stat="identity",position="dodge") + scale_x_discrete(labels = breaks) +  ylab("Percentage") +xlab("Carat")

【讨论】:

    【解决方案3】:

    幸运的是,就我而言,罗夏的答案非常有效。我在这里是为了避免使用 Megan Halbrook 提出的解决方案,直到我意识到它不是一个正确的解决方案。

    在直方图中添加一条密度线会自动将 y 轴更改为频率密度,而不是百分比。只有当 binwidth = 1 时,频率密度的值才等同于百分比。

    谷歌搜索:要绘制直方图,首先要找到每个类别的类宽度。条形的面积代表频率,因此要找到条形的高度,请将频率除以类宽度。这称为频率密度。 https://www.bbc.co.uk/bitesize/guides/zc7sb82/revision/9

    下面是一个示例,其中左侧面板显示百分比,右侧面板显示 y 轴的密度。

    library(ggplot2)
    library(gridExtra)
    
    TABLE <- data.frame(vari = c(0,1,1,2,3,3,3,4,4,4,5,5,6,7,7,8))
    
    ## selected binwidth
    bw <- 2
    
    ## plot using count
    plot_count <- ggplot(TABLE, aes(x = vari)) + 
       geom_histogram(aes(y = ..count../sum(..count..)*100), binwidth = bw, col =1) 
    ## plot using density
    plot_density <- ggplot(TABLE, aes(x = vari)) + 
       geom_histogram(aes(y = ..density..), binwidth = bw, col = 1)
    
    ## visualize together
    grid.arrange(ncol = 2, grobs = list(plot_count,plot_density))
    

    ## visualize the values
    data_count <- ggplot_build(plot_count)
    data_density <- ggplot_build(plot_density)
    
    ## using ..count../sum(..count..) the values of the y axis are the same as 
    ## density * bindwidth * 100. This is because density shows the "frequency density".
    data_count$data[[1]]$y == data_count$data[[1]]$density*bw * 100
    ## using ..density.. the values of the y axis are the "frequency densities".
    data_density$data[[1]]$y == data_density$data[[1]]$density
    
    
    ## manually calculated percentage for each range of the histogram. Note 
    ## geom_histogram use right-closed intervals.
    min_range_of_intervals <- data_count$data[[1]]$xmin
    
    for(i in min_range_of_intervals)
      cat(paste("Values >",i,"and <=",i+bw,"involve a percent of",
                sum(TABLE$vari>i & TABLE$vari<=(i+bw))/nrow(TABLE)*100),"\n")
    
    # Values > -1 and <= 1 involve a percent of 18.75 
    # Values > 1 and <= 3 involve a percent of 25 
    # Values > 3 and <= 5 involve a percent of 31.25 
    # Values > 5 and <= 7 involve a percent of 18.75 
    # Values > 7 and <= 9 involve a percent of 6.25 
    

    【讨论】:

      【解决方案4】:

      当我尝试 Rorschach 的答案时,由于不太明显的原因,它对我不起作用,但我想评论说,如果你愿意在直方图中添加密度线,一旦你这样做,它会自动改变y 轴到百分比。

      例如,我有一个二进制结果 (0,1) 的“剂量”计数

      此代码生成以下图表:

      ggplot(data, aes(x=siadoses, fill=recallbin, color=recallbin)) +
        geom_histogram(binwidth=1, alpha=.5, position='identity') 
      

      但是当我在我的 ggplot 代码中包含一个密度图并添加 y=..density.. 时,我得到了这个带有 Y 百分比的图

      ggplot(data, aes(x=siadoses, fill=recallbin, color=recallbin)) +
        geom_histogram(aes(y=..density..), binwidth=1, alpha=.5, position='identity') +
        geom_density(alpha=.2)
      

      一种解决您最初问题的方法,但我想我会分享。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-21
        • 1970-01-01
        • 2014-01-30
        • 1970-01-01
        • 1970-01-01
        • 2018-11-04
        相关资源
        最近更新 更多