geom_step的空心直方图或分级

时间:2014-05-15 17:59:55

标签: r ggplot2 ggproto

我想绘制一个空心直方图,其中没有绘制垂直条,但只是一个轮廓。我找不到用geom_histogram做任何事情的方法。 geom_step + stat_bin组合似乎可以完成这项工作。但是,根据步骤的geom_step参数值,stat_bin + direction=的区域会向右或向左移动半个区域。似乎正在做它的“步骤”WRT bin中心。有没有办法改变这种行为,所以它会在bin边缘做“步骤”?

以下是插图:

d <- data.frame(x=rnorm(1000))
qplot(x, data=d, geom="histogram",
      breaks=seq(-4,4,by=.5), color=I("red"), fill = I("transparent")) +
geom_step(stat="bin", breaks=seq(-4,4,by=.5), color="black", direction="vh")

enter image description here

7 个答案:

答案 0 :(得分:12)

我建议像这样制作新的Geom:

library(ggplot2)
library(proto)

geom_stephist <- function(mapping = NULL, data = NULL, stat="bin", position="identity", ...) {
  GeomStepHist$new(mapping=mapping, data=data, stat=stat, position=position, ...)
}

GeomStepHist <- proto(ggplot2:::Geom, {
  objname <- "stephist"

  default_stat <- function(.) StatBin
  default_aes <- function(.) aes(colour="black", size=0.5, linetype=1, alpha = NA)

  reparameterise <- function(., df, params) {
    transform(df,
              ymin = pmin(y, 0), ymax = pmax(y, 0),
              xmin = x - width / 2, xmax = x + width / 2, width = NULL
    )
  }

  draw <- function(., data, scales, coordinates, ...) {
    data <- as.data.frame(data)[order(data$x), ]

    n <- nrow(data)
    i <- rep(1:n, each=2)
    newdata <- rbind(
      transform(data[1, ], x=xmin, y=0),
      transform(data[i, ], x=c(rbind(data$xmin, data$xmax))),
      transform(data[n, ], x=xmax, y=0)
    )
    rownames(newdata) <- NULL

    GeomPath$draw(newdata, scales, coordinates, ...)
  }
  guide_geom <- function(.) "path"
})

这也适用于非均匀休息。为了说明用法:

d <- data.frame(x=runif(1000, -5, 5))
ggplot(d, aes(x)) +
  geom_histogram(breaks=seq(-4,4,by=.5), color="red", fill=NA) +
  geom_stephist(breaks=seq(-4,4,by=.5), color="black")

plot

答案 1 :(得分:11)

这不是理想的,但它是我能想到的最好的:

h <- hist(d$x,breaks=seq(-4,4,by=.5))
d1 <- data.frame(x = h$breaks,y = c(h$counts,NA))

ggplot() + 
    geom_histogram(data = d,aes(x = x),breaks = seq(-4,4,by=.5),
                                 color = "red",fill = "transparent") + 
    geom_step(data = d1,aes(x = x,y = y),stat = "identity")

enter image description here

答案 2 :(得分:11)

还有一个。使用ggplot_build构建直方图的绘图对象进行渲染。从此对象中提取xy值,以用于geom_step。使用by来隐藏x值。

by <- 0.5
p1 <- ggplot(data = d, aes(x = x)) +
  geom_histogram(breaks = seq(from = -4, to = 4, by = by),
                 color = "red", fill = "transparent")

df <- ggplot_build(p1)$data[[1]][ , c("x", "y")]

p1 +
  geom_step(data = df, aes(x = x - by/2, y = y))

enter image description here

来自@Vadim Khotilovich的评论

编辑(谢谢!)

可以使用绘图对象中的xmin代替(&gt;不需要偏移调整)

df <- ggplot_build(p1)$data[[1]][ , c("xmin", "y")]

p1 +
  geom_step(data = df, aes(x = xmin, y = y))   

答案 3 :(得分:7)

另一种选择,也不太理想:

qplot(x, data=d, geom="histogram", breaks=seq(-4,4,by=.5), color=I("red"), fill = I("transparent")) +
  stat_summary(aes(x=round(x * 2 - .5) / 2, y=1), fun.y=length, geom="step")

如果你陷入困境,你可能会遗漏一些垃圾箱。只有(有点无意义)优势在于ggplot比@Joran的回答更多,尽管这是有争议的。

enter image description here

答案 4 :(得分:4)

我今天早些时候回答了我自己的评论:这是@ RosenMatev的修改版本,使用ggproto更新了v2(ggplot2_2.0.0)的答案:

GeomStepHist <- ggproto("GeomStepHist", GeomPath,
                        required_aes = c("x"),

                        draw_panel = function(data, panel_scales, coord, direction) {
                          data <- as.data.frame(data)[order(data$x), ]

                          n <- nrow(data)
                          i <- rep(1:n, each=2)
                          newdata <- rbind(
                            transform(data[1, ], x=x - width/2, y=0),
                            transform(data[i, ], x=c(rbind(data$x-data$width/2, data$x+data$width/2))),
                            transform(data[n, ], x=x + width/2, y=0)
                          )
                          rownames(newdata) <- NULL

                          GeomPath$draw_panel(newdata, panel_scales, coord)
                        }
)


geom_step_hist <- function(mapping = NULL, data = NULL, stat = "bin",
                           direction = "hv", position = "stack", na.rm = FALSE, 
                           show.legend = NA, inherit.aes = TRUE, ...) {
  layer(
    data = data,
    mapping = mapping,
    stat = stat,
    geom = GeomStepHist,
    position = position,
    show.legend = show.legend,
    inherit.aes = inherit.aes,
    params = list(
      direction = direction,
      na.rm = na.rm,
      ...
    )
  )
}

答案 5 :(得分:0)

一种类似于@Rosen Matev的简单方法(与@julou提到的ggplot2_2.0不兼容),我会 1)手动计算箱的值(使用如下所示的小功能) 2)使用geom_step() 希望这有帮助!

geom_step_hist<- function(d,binw){
  dd=NULL
  bin=min(d$y) # this enables having a first value that is = 0 (to have the left vertical bar of the plot when using geom_step)
  max=max(d$y)+binw*2 # this enables having a last value that is = 0 (to have the right vertical bar of the plot when using geom_step)
  xx=NULL
  yy=NULL
  while(bin<=max){
    n=length(temp$y[which(temp$y<bin & temp$y>=(bin-binw))])
    yy=c(yy,n)
    xx=c(xx,bin-binw)
    bin=bin+binw
    rm(n)
  }
  dd=data.frame(xx,yy)
  return(dd)
}
hist=ggplot(dd,aes(x=xx,y=yy))+
geom_step()

答案 6 :(得分:0)

TLDR:使用geom_step(..., direction = "mid")

自从Daniel Mastropietro和Dewey Dunnington implemented将“ mid”作为ggplot2 v3.3.0的direction的{​​{1}}参数的附加选项以来,这变得更加容易了:

geom_step

下面,供参考的是来自问题的代码,其格式如上述答案:

library(ggplot2)

set.seed(1)
d <- data.frame(x = rnorm(1000))
ggplot(d, aes(x)) + 
  geom_histogram(breaks = seq(-4, 4, by=.5), color="red", fill = "transparent") +
  geom_step(stat="bin", breaks=seq(-4, 4, by=.5), color = "black", direction = "mid")

reprex package(v0.3.0)于2020-09-02创建