R 在ggplot中将文本添加到geom_直方图的正确方法是什么?

R 在ggplot中将文本添加到geom_直方图的正确方法是什么?,r,ggplot2,R,Ggplot2,我在x轴和y轴上绘制了一个工资的历史图,显示了数据集中拥有这一特定工资的个人的百分比。现在我想让各个条显示每个条中有多少观察者。e、 g在我提供的样本_数据中,有多少工资在10%栏中,有多少工资在20%栏中 这是我的一个小样本数据: sample_data<- structure(list(wage = c(81L, 77L, 63L, 84L, 110L, 151L, 59L, 109L, 159L, 71L), sch

我在x轴和y轴上绘制了一个工资的历史图,显示了数据集中拥有这一特定工资的个人的百分比。现在我想让各个条显示每个条中有多少观察者。e、 g在我提供的样本_数据中,有多少工资在10%栏中,有多少工资在20%栏中

这是我的一个小样本数据:


sample_data<- structure(list(wage = c(81L, 77L, 63L, 84L, 110L, 151L, 59L, 
                                109L, 159L, 71L), school = c(15L, 12L, 10L, 15L, 16L, 18L, 11L, 
                                                             12L, 10L, 11L), expr = c(17L, 10L, 18L, 16L, 13L, 15L, 19L, 20L, 
                                                                                      21L, 20L), public = c(0L, 1L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L), 
                       female = c(1L, 1L, 1L, 1L, 0L, 0L, 1L, 0L, 1L, 0L), industry = c(63L, 
                                                                                        93L, 71L, 34L, 83L, 38L, 82L, 50L, 71L, 37L)), row.names = c("1", 
                                                                                                                                                     "2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")

基本上我对此很满意,但不管我怎么做,我都无法在我的专栏顶部找到文本。下面是一个使用stat_count但不起作用的示例:

ggplot(data = sample_data) +
  geom_histogram(aes(x = wage, y = stat(count) / sum(count)), binwidth = 4, color = "black") + 
  scale_x_continuous(breaks = seq(0, 300, by = 20)) +
  scale_y_continuous(labels = scales::percent_format()) + 
  stat_count(aes(y = ..count.., label =..count..), geom = "text")

Iv'e还尝试使用geom_文本,但没有结果

编辑:回答

也非常感谢那些回复的人。 我最终使用了teunbrand的解决方案,并做了一个小小的修改,将after_stat(density)改为after_stat(count)/sum(count)

以下是“最终”代码:

ggplot(sample_data) +
  geom_histogram(
    aes(x = wage,
        y = after_stat(count) / sum(count)),
    binwidth = 4, colour = "black"
  ) +
  stat_bin(
    aes(x = wage,
        y = after_stat(count) / sum(count),
        label = after_stat(ifelse(count == 0, "", count))),
    binwidth = 4, geom = "text", vjust = -1) + 
  scale_x_continuous(breaks = seq(0, 300, by = 20)) +
  scale_y_continuous(labels = scales::percent_format()) 


就我个人而言,我觉得关于这个问题的现有答案有些令人沮丧,而我希望有一个更简单的解决方案。我个人也不喜欢直方图中出现的0,使用
stat\u bin
定位有时会令人沮丧。由于不得不这样做几次,我通常会回到一些手动计算,并将
geom\u rect
geom\u文本
/
geom\u标签
结合使用。也许有一天我会坐下来,实际创建我认为需要的3个函数来创建一个合适的
geom.*
。在此之前,基本理念是:

  • 使用
    hist
  • 使用
    geom\u rect
    (我们的“
    geom\u hist
    ”替代品)和
    geom\u文本所需的美学技巧,将数据更改为
    data.frame
  • 在必要的图层中手动绘制此数据
  • #“计算用于创建包含标签的ggplot手动直方图的数据
    #'
    #“@param bardata从\code{hist(data,plot=FALSE)}输出
    #“@param probs标签应该是概率标度还是非概率标度?
    #' 
    #“@返回一个\code{data.frame},列为xmin、ymin、xmax、ymax、mids和label
    
    创建_gg_hist_df不同的层通常不共享状态信息,因此您可以使用与直方图相同的统计(
    stat_bin()
    )来显示标签。然后,您可以使用
    after_stat()
    使用图层stat部分的计算变量来制作标签

    库(ggplot2)
    
    示例_数据相关:我认为这不起作用:“y”的比例已经存在。为“y”添加另一个比例,它将替换现有比例。错误:stat_bin()需要一个x或y美学。也许新的ish
    在_stat
    之后可能会有所帮助(我没有使用过它…)-请参见示例,如果它是关于
    geom\u直方图的描述的
    。对于直方图图中的这个零问题,它是有用的,并且是一个救生装置。通过使用geom\u col而不是geom\u rect,您可以大大简化此代码。ymin始终为0,ymax=y,mids=x。例如,列的宽度为
    2*(bardata,abs(breaks[1]-mids[1]))
    ,(顺便说一句,+1)很棒!这很有用。请问“after_stat(ifelse(count==0,”,count)”是什么意思?我猜这意味着如果值为0,它将不会打印标签?没错:
    after_stat()
    访问
    ?stat bin
    中记录的“计算变量”。然后
    ifelse()
    部分使用空字符串(
    )如果
    count
    计算变量为0,并且在非零时使用
    count
    本身。
    ggplot(sample_data) +
      geom_histogram(
        aes(x = wage,
            y = after_stat(count) / sum(count)),
        binwidth = 4, colour = "black"
      ) +
      stat_bin(
        aes(x = wage,
            y = after_stat(count) / sum(count),
            label = after_stat(ifelse(count == 0, "", count))),
        binwidth = 4, geom = "text", vjust = -1) + 
      scale_x_continuous(breaks = seq(0, 300, by = 20)) +
      scale_y_continuous(labels = scales::percent_format()) 
    
    
    #' Compute data for creating a manual histogram with ggplot including labels 
    #'
    #' @param bardata output from \code{hist(data, plot = FALSE)}
    #' @param probs should labels be in probability scale or non-probability scales?
    #' 
    #' @return a \code{data.frame} with columns xmin, ymin, xmax, ymax, mids and label
    create_gg_hist_df <- function(bardata, probs = TRUE){
      nb <- length(bardata$breaks)
      xmax <- bardata$breaks[-1L]
      xmin <- bardata$breaks[-nb]
      mids <- bardata$mids
      ymin <- integer(nb - 1)
      ymax <- bardata$count / sum(bardata$count)
      label <- if(!probs) ymax else bardata$count
      data.frame(xmin = xmin,
                 ymin = ymin,
                 xmax = xmax, 
                 ymax = ymax, 
                 mids = mids, 
                 label = label)
    }
    ggbardata <- create_gg_hist_df(hist(sample_data$wage, 
                                        # breaks based on ggplot2 when "width" is supplied
                                        breaks = ggplot2:::bin_breaks_width(range(sample_data$wage), 
                                                                            width = 4)$breaks, 
                                        plot = FALSE))
    
    ggbardata %>% 
      # Remove "0" columns ( I don't want them. That is my preference ) 
      filter(ymax > 0) %>% 
      ggplot(aes(xmin = xmin, xmax = xmax, 
                          ymin = ymin, ymax = ymax, 
                          label = label)) + 
      # Add histogram
      geom_rect(color = 'black') + 
      # Add text
      geom_text(aes(x = mids, y = ymax), nudge_y = 0.005) + 
      scale_y_continuous(labels = scales::percent_format()) + 
      labs(x = 'wage', y = 'frequency')