控制自定义ggplot2 geoms中的间距

时间:2014-06-10 22:57:08

标签: r coding-style ggplot2 data-visualization

我正在创建一个自定义的ggplot geom来代表Edward Tufte的第二个boxplot Tufte #1 can lead to misinterpretations of data, but #2 is nice

最终的目标是能够将其用作轴来简洁地显示边际分布。 我的工作基于Jeffrey Arnoldggthemes

我得到了一个看起来正确的输出,但是在一般情况下使其工作导致了手头的问题。 tufte box plots in ggplot2

下面是用于绘制中间线的代码(即替换框的行):

median.thickness <- 0.25
box.offset <- 0.01
boxdata <- data.frame(
    x = data$x + box.offset,
    xend = data$x + box.offset,
    y = c(data$upper, data$lower),
    yend = c(data$middle + median.thickness, data$middle - median.thickness),
    alpha = NA,
    common)

显然,值median.thicknessbox.offset需要根据绘图的范围而有所不同,因此根据这些值计算它们是理想的。有没有办法在geom中实现这个目标?

2 个答案:

答案 0 :(得分:0)

不可否认,不是你要求的,但这是一个如何用基本图形实现这一目标的例子。

tufte <- function(x, groups, data, offset=0.15, lwd=2, 
                  xlab=NULL, ylab=NULL) {
  if(is.null(xlab)) xlab <- deparse(substitute(groups))
  if(is.null(ylab)) ylab <- deparse(substitute(x))
  b <- boxplot(eval(substitute(x~groups)), data, plot=FALSE)
  nm <- b$names
  stats <- b$stats
  plot.new()
  plot.window(ylim=range(pretty(range(stats))), xlim=c(0.5, ncol(stats)+0.5))
  mdn.span <- 0.15*min(stats[4, ] - stats[2, ])
  invisible({
    segments(rep(seq_len(ncol(stats)), each=2), c(stats[c(1, 4), ]),
             y1=c(stats[c(2, 5), ]), lwd=lwd, lend=1)
    segments(seq_len(ncol(stats)) + offest, c(stats[2, ]),
             y1=c(stats[4, ]), lwd=lwd, lend=1)
  })
  segments(seq_len(ncol(stats)) + offset, stats[3, ] - mdn.span, 
           y1=stats[3, ] + mdn.span, col='white', lwd=3, lend=1)
  axis(1, at=seq_len(ncol(stats)), labels=nm)
  axis(2, las=1)
  title(xlab=xlab, ylab=ylab)
  box(lwd=2)
}

tufte(weight, feed, chickwts)

这里,x偏移被设置为一个常数,这对我来说是有意义的,因为有了更多的组,x轴的范围会更大,你会想要更小的偏移(我想?)。表示中位数的间隙的高度定义为IQR最小的组的四分位数范围的五分之一。但是,这意味着如果存在IQR非常小的组,则所有组的绘图都将受到影响。

tufte

答案 1 :(得分:0)

我想我已经找到了一个很好的解决方案。

boxdata <- data.frame(
    x = data$x,
    xend = data$x,
    y = c(data$upper, data$lower),
    yend = c(data$middle, data$middle),
    alpha = NA,
    common)
  box_grob <- GeomSegment$draw(boxdata, ...)
  offset <- 0.004
  box_grob$x0 <- box_grob$x0 + unit(offset * common$size, "npc")
  box_grob$x1 <- box_grob$x1 + unit(offset * common$size, "npc")
  box_grob$y1 <- box_grob$y1 + unit(c(1.5 * offset, -1.5 * offset), "npc")

此代码生成与问题中公布的图相同的图,并根据线条粗细进行适当缩放。