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

nuypyhwy  于 2023-05-20  发布在  其他
关注(0)|答案(5)|浏览(141)

例如,考虑使用数据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()

误差线在图上是水平的,但在图例中是垂直的,这一事实让我很烦恼:)我如何旋转这些符号?

2hh7jdfx

2hh7jdfx1#

调整图例键

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))
}

然后密谋

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()
jexiocij

jexiocij2#

我没有想出一个在正常的ggplot2工作流程中工作的答案,所以现在,这里有一个黑客的答案。关闭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))

另一种选择是使用网格函数将图例键grobs旋转90度,但我将把它留给比我更熟练的grid

shyt4zoc

shyt4zoc3#

更新答案

ggplot2 3.3.0解决了这个问题。当使用xminxmax参数时,使用geom_pointrange()函数将在图例中呈现水平误差条:

library(ggplot2)
library(dplyr)

df <- mtcars |> 
  mutate(gear = as.factor(gear),
         am = as.factor(am)) |> 
  group_by(gear, am) |> 
  summarise(cyl_mean = mean(cyl),
            cyl_upr =  mean(cyl) + sd(cyl)/sqrt(length(cyl)),
            cyl_lwr = mean(cyl) - sd(cyl)/sqrt(length(cyl)))

ggplot(df, 
       aes(x=cyl_mean, y=gear, 
           color = am, group = am)) +
  geom_pointrange(aes(xmin = cyl_lwr,
                      xmax = cyl_upr),
                  position = position_dodge(0.25))

创建于2023-05-16带有reprex v2.0.2

旧答案

ggstance软件包提供了一个易于实施的解决方案:

library(ggplot2)
library(ggstance)

ggplot(mtcars,aes(x=cyl,y=gear)) + stat_summaryh(aes(color=as.factor(rep(1:2,16))),
                                                fun.data=mean_cl_boot_h, position = position_dodgev(height = 0.4))

或者作为geom

df <- data.frame(x = 1:3, y = 1:3)
ggplot(df, aes(x, y, colour = factor(x))) +
     geom_pointrangeh(aes(xmin = x - 1, xmax = x + 1))
mkshixfv

mkshixfv4#

按照@eipi10的建议,使用grid函数来编辑grob-相关的grob是段。有两种可能性:1)旋转节段滑车;或2)编辑片段grob的端点的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)
alen0pnh

alen0pnh5#

编辑自:https://gist.github.com/grantmcdermott/d86af2b8f21f4082595c0e717eea5a90
要点是使用geom_pointrangeh from ggstance,并记住指定aes w.r. t。x轴。

library(tidyverse)
library(broom)
library(hrbrthemes) 
library('ggstance')
library('jtools')

df = 
  mtcars %>%
  mutate(vs = factor(vs), am = factor(am))

fit1 = lm(mpg ~ vs * am * wt, data = df) 
fit1_coefs = tidy(fit1, conf.int = T) 

fit2 = lm(mpg ~ vs / am / wt, data = df)
fit2_coefs = tidy(fit2, conf.int = T) 

bind_rows(
  fit1_coefs %>% mutate(model = "Model 1"),
  fit2_coefs %>% mutate(model = "Model 2")
) %>%
  filter(grepl("wt", term)) %>%
  ## Optional regexp work to make plot look nicier  
  mutate(
    am = ifelse(grepl("am1", term), "Automatic", "Manual"),
    vs = ifelse(grepl("vs1", term), "V-shaped", "Straight"),
    x_lab = paste(am, vs, sep="\n")
  ) %>%
  ggplot(aes(col = model,y=x_lab, x=estimate, xmin=conf.low, xmax=conf.high)) +
  geom_pointrangeh(position = position_dodge(width = 0.5)) +
  guides(color = guide_legend(reverse = TRUE)) +
  geom_vline(xintercept = 0, col = "black",lty=4) +
    labs(x = NULL, y = NULL,title = "Title") +
  theme_nice() +
  theme(plot.title = element_text(hjust = 0.5))

相关问题