Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用ggproto扩展ggplot2箱线图?_R_Ggplot2_Fonts_Boxplot_Ggproto - Fatal编程技术网

如何使用ggproto扩展ggplot2箱线图?

如何使用ggproto扩展ggplot2箱线图?,r,ggplot2,fonts,boxplot,ggproto,R,Ggplot2,Fonts,Boxplot,Ggproto,我经常在工作中使用箱线图,喜欢ggplot2美学。但标准的geom_箱线图缺少两件对我来说很重要的东西:胡须末端和中间带标签。感谢这里的信息,我编写了一个函数: gBoxplot <- function(formula = NULL, data = NULL, font = "CMU Serif", fsize = 18){ require(ggplot2) vars <- all.vars(formula) response <- vars[1] factor

我经常在工作中使用箱线图,喜欢
ggplot2
美学。但标准的
geom_箱线图
缺少两件对我来说很重要的东西:胡须末端和中间带标签。感谢这里的信息,我编写了一个函数:

gBoxplot <- function(formula = NULL, data = NULL, font = "CMU Serif", fsize = 18){
  require(ggplot2)
  vars <- all.vars(formula)
  response <- vars[1]
  factor <- vars[2]
  # A function for medians labelling
  fun_med <- function(x){
    return(data.frame(y = median(x), label = round(median(x), 3)))
  }
  p <- ggplot(data, aes_string(x = factor, y = response)) +
  stat_boxplot(geom = "errorbar", width = 0.6) +
  geom_boxplot() +
  stat_summary(fun.data = fun_med, geom = "label", family = font, size = fsize/3, 
                                                                         vjust = -0.1) +
  theme_grey(base_size = fsize, base_family = font)
  return(p)
}

对我来说已经足够好了,但是有一些限制(不能使用自动回避等),最好是基于
geom\u箱线图
制作一个新的geom。我读过这个小插曲,但不明白如何实现它。
任何帮助都将不胜感激。

所以我已经考虑了一会儿了。基本上,当您创建一个新的基本体时,您通常会编写以下内容的组合:

  • A层功能
  • A统计ggproto
  • Ageom ggproto
  • 只有层功能需要对用户可见。如果您需要一些新的方法来转换数据以生成原语,只需编写一个stat ggproto。如果要创建一些新的基于网格的图形,只需编写一个geom ggproto

    在这种情况下,我们基本上是将已经存在的层功能组合起来,我们实际上不需要编写新的ggprotos。写一个新的层函数就足够了。此图层功能将创建您已经使用的三个图层,并按照您的意愿映射参数。在这种情况下:

    • 第1层–使用
      geom_errorbar
      stat_boxplot
      –获取我们的errorbar
    • 第二层–使用
      geom\u箱线图
      stat\u箱线图
      -创建箱线图
    • 第3层-用户
      geom_标签
      stat_摘要
      -创建文本标签,平均值位于框的中心
    当然,您可以编写一个新的stat ggproto和一个新的geom ggproto,同时完成所有这些任务。或者你可以把
    stat\u summary
    stat\u boxplot
    组合成一个,还有三个geom protos,这是用一层来实现的。但除非我们有效率问题,否则没有什么意义

    无论如何,代码如下:

    geom_myboxplot <- function(formula = NULL, data = NULL,
                               stat = "boxplot", position = "dodge",coef=1.5,
                               font = "sans", fsize = 18, width=0.6,
                               fun.data = NULL, fun.y = NULL, fun.ymax = NULL,
                               fun.ymin = NULL, fun.args = list(),
                               outlier.colour = NULL, outlier.color = NULL,
                               outlier.shape = 19, outlier.size = 1.5,outlier.stroke = 0.5,
                               notch = FALSE,  notchwidth = 0.5,varwidth = FALSE,
                               na.rm = FALSE, show.legend = NA,
                               inherit.aes = TRUE,...) {
        vars <- all.vars(formula)
        response <- vars[1]
        factor <- vars[2]
        mymap <- aes_string(x=factor,y=response)
        fun_med <- function(x) {
            return(data.frame(y = median(x), label = round(median(x), 3)))
        }
        position <- position_dodge(width)
        l1 <- layer(data = data, mapping = mymap, stat = StatBoxplot,
                geom = "errorbar", position = position, show.legend = show.legend,
                inherit.aes = inherit.aes, params = list(na.rm = na.rm,
                    coef = coef, width = width, ...))
        l2 <- layer(data = data, mapping = mymap, stat = stat, geom = GeomBoxplot,
                position = position, show.legend = show.legend, inherit.aes = inherit.aes,
                params = list(outlier.colour = outlier.colour, outlier.shape = outlier.shape,
                    outlier.size = outlier.size, outlier.stroke = outlier.stroke,
                    notch = notch, notchwidth = notchwidth, varwidth = varwidth,
                    na.rm = na.rm, ...))
        l3 <- layer(data = data, mapping = mymap, stat = StatSummary,
                geom = "label", position = position, show.legend = show.legend,
                inherit.aes = inherit.aes, params = list(fun.data = fun_med,
                    fun.y = fun.y, fun.ymax = fun.ymax, fun.ymin = fun.ymin,
                    fun.args = fun.args, na.rm=na.rm,family=font,size=fsize/3,vjust=-0.1,...))
        return(list(l1,l2,l3))
    }
    
    它们看起来是这样的:

    ggplot(mpg) +
      geom_myboxplot( hwy ~ class, font = "sans",fsize = 18)+
      theme_grey(base_family = "sans",base_size = 18 )
    

    注意:我们实际上不必使用
    函数,我们可以使用原始的
    stat\u箱线图
    geom\u箱线图
    stat\u summary
    调用来代替它们。但是,如果我们想从定制的箱线图中控制它们,我们仍然必须填写所有参数,因此我认为这样做更清楚——至少从结构而不是功能的角度来看。也许不是,这是品味的问题


    我也没有那种看起来更好的字体。但我不想追踪并安装它。

    你觉得怎么样?非常感谢,@MikeWise!请参阅评论以获取您的答案。呃,哪一条评论?如果你喜欢,你能接受这个答案吗?要做到这一点,请单击我答案左上角“投票数”下方的灰色复选标记。好的,我接受了!我对任何答案都失去了希望,所以现在看看你的答案。事实上,这正是问题所在:工作示例和一些需要思考的理论。需要一些时间把想法牢记在心(英语不是我的母语)。我使用的字体是D.Knuth的classic.Great的unicode版本。很高兴你喜欢。请接受答案。谢谢。如果你还有两点,你也可以投票表决。也许下次:)@MikeWise你知道我如何调整这种方法来调整点或多边形的位置吗?我希望开发一个函数,其中重叠的几何对象被移动,这样它们就不会重叠,可能使用力方向的方法。上面的示例中,任何指针都会移动这些点以避免碰撞。你是在谈论你定义的新gemos,还是在寻找其他已经存在的gemos。
    ggplot(mpg) +
      geom_myboxplot( hwy ~ class, font = "sans",fsize = 18)+
      theme_grey(base_family = "sans",base_size = 18 )