如何在ggplot2中旋转图例符号?

时间:2023-02-09 21:39:02

Consider for example this plot using the data mtcars and the function coord_flip

例如,考虑使用数据mtcars和函数coord_flip的这个图

library(ggplot2)
library(Hmisc)

ggplot(mtcars,aes(x=gear,y=cyl)) + stat_summary(aes(color=as.factor(rep(1:2,16))),
fun.data=mean_cl_boot, position=position_dodge(0.4)) + coord_flip()

如何在ggplot2中旋转图例符号?

The fact that error bars are horizontal on the graph but vertical in the legend bothers me :) How can I rotate these symbols?

错误栏在图表上是水平但在图例中垂直的事实困扰我:)我如何旋转这些符号?

3 个解决方案

#1


3  

I'm not coming up with an answer that works within the normal ggplot2 workflow, so for now, here's a hacky answer. Turn off the stat_summary legend. Then, add point and line geoms with data that is outside the range of the actual data you want to plot. This will create the point and horizontal line legend that you want. Then set the plot axis limits to include only the range of your real data, so that the fake data points are not visible.

我没有想出一个在正常的ggplot2工作流程中有效的答案,所以现在,这是一个hacky的答案。关闭stat_summary图例。然后,使用超出要绘制的实际数据范围的数据添加点和线主题。这将创建所需的点和水平线图例。然后将绘图轴限制设置为仅包括实际数据的范围,以便伪数据点不可见。

ggplot(mtcars, aes(x=gear, y=cyl, color=as.factor(rep(1:2,16)))) + 
  stat_summary(fun.data=mean_cl_boot, position=position_dodge(0.4), show.legend=FALSE) + 
  geom_line(aes(y=cyl-100)) +
  geom_point(aes(y=cyl-100), size=2.5) +
  coord_flip(ylim=range(mtcars$cyl)) 

如何在ggplot2中旋转图例符号?

Another option would be to rotate the legend-key grobs by 90 degrees using grid functions, but I'll leave that for someone who's more skilled with grid than I am.

另一个选择是使用网格函数将图例键的凹凸旋转90度,但我会留给那些比我更熟练的格栅的人。

#2


5  

Tweak the legend key

调整图例键

GeomPointrange$draw_key <-  function (data, params, size)     {

         draw_key_vpath <- function (data, params, size) {
           # only need to change the x&y coords so that the line is horizontal
           # originally, the vertical line was `0.5, 0.1, 0.5, 0.9`
              segmentsGrob(0.1, 0.5, 0.9, 0.5, 
              gp = gpar(col = alpha(data$colour, data$alpha), 
              lwd = data$size * .pt, lty = data$linetype, 
              lineend = "butt"), arrow = params$arrow)
              }

    grobTree(draw_key_vpath(data, params, size), 
             draw_key_point(transform(data, size = data$size * 4), params))
}

Then plot

然后情节

 ggplot(mtcars,aes(x=gear,y=cyl)) + 
    stat_summary(aes(color=as.factor(rep(1:2,16))),
                  fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
    coord_flip()

#3


2  

Following up @eipi10's suggestion to use grid functions to edit the grobs - the relevant grobs are segments. There are two possibilities: 1) rotate the segment grobs; or 2) edit the x and y coordinates of the endpoints of the segment grobs.

继续@ eipi10建议使用网格函数来编辑grobs - 相关的grob是段。有两种可能性:1)旋转节段凹凸;或者2)编辑段grobs的端点的x和y坐标。

library(ggplot2)
library(Hmisc)

library(grid)

p = ggplot(mtcars,aes(x=gear,y=cyl)) + 
    stat_summary(aes(color=as.factor(rep(1:2,16))),
                  fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
    coord_flip()

g = ggplotGrob(p)

# Get names of segment grobs
grid.ls(grid.force(g))$name   # "GRID.segments"

# Check the structure of the segment grobs
str(getGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE))

# Edit the segment grobs using the editGrob() function
# 1) Rotate the segments
    g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,
        vp = viewport(angle = 90)) 

# 2) set end points of segments
#    g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,  
#         x0 = unit(0.1, "npc"), y0 = unit(0.5, "npc"), x1 = unit(0.9, "npc"), y1 = unit(0.5, "npc"))

# Draw it
grid.newpage()
grid.draw(g)

#1


3  

I'm not coming up with an answer that works within the normal ggplot2 workflow, so for now, here's a hacky answer. Turn off the stat_summary legend. Then, add point and line geoms with data that is outside the range of the actual data you want to plot. This will create the point and horizontal line legend that you want. Then set the plot axis limits to include only the range of your real data, so that the fake data points are not visible.

我没有想出一个在正常的ggplot2工作流程中有效的答案,所以现在,这是一个hacky的答案。关闭stat_summary图例。然后,使用超出要绘制的实际数据范围的数据添加点和线主题。这将创建所需的点和水平线图例。然后将绘图轴限制设置为仅包括实际数据的范围,以便伪数据点不可见。

ggplot(mtcars, aes(x=gear, y=cyl, color=as.factor(rep(1:2,16)))) + 
  stat_summary(fun.data=mean_cl_boot, position=position_dodge(0.4), show.legend=FALSE) + 
  geom_line(aes(y=cyl-100)) +
  geom_point(aes(y=cyl-100), size=2.5) +
  coord_flip(ylim=range(mtcars$cyl)) 

如何在ggplot2中旋转图例符号?

Another option would be to rotate the legend-key grobs by 90 degrees using grid functions, but I'll leave that for someone who's more skilled with grid than I am.

另一个选择是使用网格函数将图例键的凹凸旋转90度,但我会留给那些比我更熟练的格栅的人。

#2


5  

Tweak the legend key

调整图例键

GeomPointrange$draw_key <-  function (data, params, size)     {

         draw_key_vpath <- function (data, params, size) {
           # only need to change the x&y coords so that the line is horizontal
           # originally, the vertical line was `0.5, 0.1, 0.5, 0.9`
              segmentsGrob(0.1, 0.5, 0.9, 0.5, 
              gp = gpar(col = alpha(data$colour, data$alpha), 
              lwd = data$size * .pt, lty = data$linetype, 
              lineend = "butt"), arrow = params$arrow)
              }

    grobTree(draw_key_vpath(data, params, size), 
             draw_key_point(transform(data, size = data$size * 4), params))
}

Then plot

然后情节

 ggplot(mtcars,aes(x=gear,y=cyl)) + 
    stat_summary(aes(color=as.factor(rep(1:2,16))),
                  fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
    coord_flip()

#3


2  

Following up @eipi10's suggestion to use grid functions to edit the grobs - the relevant grobs are segments. There are two possibilities: 1) rotate the segment grobs; or 2) edit the x and y coordinates of the endpoints of the segment grobs.

继续@ eipi10建议使用网格函数来编辑grobs - 相关的grob是段。有两种可能性:1)旋转节段凹凸;或者2)编辑段grobs的端点的x和y坐标。

library(ggplot2)
library(Hmisc)

library(grid)

p = ggplot(mtcars,aes(x=gear,y=cyl)) + 
    stat_summary(aes(color=as.factor(rep(1:2,16))),
                  fun.data=mean_cl_boot, position=position_dodge(0.4)) + 
    coord_flip()

g = ggplotGrob(p)

# Get names of segment grobs
grid.ls(grid.force(g))$name   # "GRID.segments"

# Check the structure of the segment grobs
str(getGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE))

# Edit the segment grobs using the editGrob() function
# 1) Rotate the segments
    g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,
        vp = viewport(angle = 90)) 

# 2) set end points of segments
#    g <- editGrob(grid.force(g), gPath("GRID.segments"), grep = TRUE, global = TRUE,  
#         x0 = unit(0.1, "npc"), y0 = unit(0.5, "npc"), x1 = unit(0.9, "npc"), y1 = unit(0.5, "npc"))

# Draw it
grid.newpage()
grid.draw(g)