【问题标题】:How to reorder the legend in ggplot and pltly?如何重新排序ggplot和pltly中的图例?
【发布时间】:2020-07-12 20:44:04
【问题描述】:

我有一个非常简单的问题,但我不知道如何解决:我正在绘制李克特比例条形图。

likert_results2 <-  structure(list(Survey = c("Post survey \nN= 274", "Post survey \nN= 274", 
                                              "Post survey \nN= 274", "Post survey \nN= 274", "Post survey \nN= 274", 
                                              "Post survey \nN= 274", "Pre survey \nN= 429", "Pre survey \nN= 429", 
                                              "Pre survey \nN= 429", "Pre survey \nN= 429", "Pre survey \nN= 429", 
                                              "Pre survey \nN= 429", "Post survey \nN= 276", "Post survey \nN= 276", 
                                              "Post survey \nN= 276", "Post survey \nN= 276", "Post survey \nN= 276", 
                                              "Post survey \nN= 276", "Pre survey \nN= 428", "Pre survey \nN= 428", 
                                              "Pre survey \nN= 428", "Pre survey \nN= 428", "Pre survey \nN= 428", 
                                              "Pre survey \nN= 428"), Response = c("agree", "disagree", "neither agree nor disagree", 
                                                                                   "somewhat agree", "somewhat disagree", "strongly agree", "agree", 
                                                                                   "disagree", "neither agree nor disagree", "somewhat agree", "somewhat disagree", 
                                                                                   "strongly agree", "agree", "disagree", "neither agree nor disagree", 
                                                                                   "somewhat agree", "somewhat disagree", "strongly agree", "agree", 
                                                                                   "disagree", "neither agree nor disagree", "somewhat agree", "somewhat disagree", 
                                                                                   "strongly agree"), Question = c("q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q1", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2", 
                                                                                                                   "q2"
                                                                                   ), prop = c(0.17, 0.21, 0.08, 0.29, 0.16, 0.09, 0.14, 0.16, 0.16, 
                                                                                               0.3, 0.18, 0.07, 0.13, 0.21, 0.11, 0.29, 0.19, 0.07, 0.11, 0.18, 
                                                                                               0.18, 0.28, 0.21, 0.06)), class = c("tbl_df", "tbl", "data.frame"
                                                                                               ), row.names = c(NA, -24L))

# Create data frame with labels
prop_labels <- likert_results2 %>%
  mutate(
    position = case_when(
      Response == "somewhat disagree" | Response == "disagree" | Response == "strongly disagree" ~ "left",
      Response == "neither agree nor disagree" ~ "center",
      Response == "somewhat agree" | Response == "agree"  | Response == "strongly agree" ~ "right"
    )
  ) %>%
  group_by(Question, Survey, position) %>%
  dplyr::summarize(.,label = sum(prop * 100)) %>%
  pivot_wider(names_from = position,
              values_from = label)

# Data frame with left side values
high_columns <- likert_results2 %>%
  filter( Response == "strongly disagree" |  Response == "disagree"| Response == "somewhat disagree" | Response == "neither agree nor disagree") %>%
  mutate(prop = case_when(Response == "strongly disagree" ~ prop * 100,
                          Response == "disagree" ~ prop * 100,
                          Response == "somewhat disagree" ~ prop * 100,
                          Response == "neither agree nor disagree" ~ prop / 2 * 100
  ))
# Data frame with right side values
low_columns <- likert_results2 %>%
  filter(Response == "neither agree nor disagree" | Response == "somewhat agree" | Response == "agree" | Response == "strongly agree") %>%
  mutate(prop = case_when(Response == "neither agree nor disagree" ~ prop / 2 * 100,
                          Response == "somewhat agree" ~ prop * 100,
                          Response == "agree" ~ prop * 100,
                          Response == "strongly agree" ~ prop * 100,
  )) 
# Define empty ggplot object
p <- ggplot() +
  # Add central black line
  geom_hline(yintercept = 0,
             linetype="dashed",
             colour ="darkgrey") +
  # Add right side columns
  geom_bar(
    data = high_columns,
    mapping = aes(x = Survey,
                  y = prop,
                  fill = Response),
    position = position_stack(reverse = F),
    stat = "identity"
  ) +
  # Add left side columns
  geom_bar(
    data = low_columns,
    mapping = aes(x = Survey,
                  y = -prop,
                  fill = Response),
    position = position_stack(reverse = T),
    stat = "identity"
  ) +
  #Right side labels
  geom_text(
    data = prop_labels,
    mapping = aes(
      x = Survey,
      y = -100,
      label = paste(ifelse(is.na(right),0,round(right)) , "%", sep = "")),
    hjust = 1,
    color = "black",
    size = 3
  ) +
  # Central labels
  geom_text(
    data = prop_labels,
    mapping = aes(
      x = Survey,
      y = 0,
      label = paste(ifelse(is.na(center),0,round(center)) , "%", sep = "")),
    hjust = 0.5,
    color = "black",
    size = 3
  ) +
  # Left side labels
  geom_text(
    data = prop_labels,
    mapping = aes(
      x = Survey,
      y = 100,
      label = paste(ifelse(is.na(left),0,round(left)) , "%", sep = "")),
    hjust = -0.2,
    color = "black",
    size = 3
  )  +
  # Scale formatting
  scale_y_continuous(
    breaks = seq(-100, 100, 50),
    limits = c(-105, 105),
    labels = abs
  )  +
  # More formatting
  theme(legend.title = element_blank(),
        legend.position = "right",
        axis.ticks = element_blank(),
        strip.background = element_rect(fill = "#F0F0F0",
                                        color = "#F0F0F0"),
        panel.background = element_blank(),
        panel.border = element_rect(
          colour = "#F0F0F0",
          fill = NA,
          size = 1.5)
  ) +
  facet_wrap(~ Question, scales="free_y",ncol = 1) +
  coord_flip() +
  ylab("Percent of students") +
  xlab("") +
  # Change Likert labels
  scale_fill_manual(name = "Response", values = c("#1E4384","#6495CF","#7278A8","#AFA690", "#E9739B","#B54461","#B1235E") ,labels=c("strongly agree","agree","somewhat agree","neither agree nor disagree","somewhat disagree","disagree","strongly disagree"))
# Print the plot
p 

#plotly graph
ggplotly(p, width = 1200, height = 800) 

我遇到的问题是以正确的方式订购图例中的项目。如果我在没有scale_fill_manual 的情况下运行代码,情节如下所示:

[![在此处输入图片描述][1]][1]

当我添加 scale_fill_manual 时,除了图例顺序之外,所有内容都是正确的

当我用scale_fill_manual 指定顺序时,我得到了:这确实将图例中的顺序更改为更正,但不是带颜色的正方形:

[![在此处输入图片描述][2]][2]

当我运行 ggplotly 时,该命令也会删除我指定的所有订单。 [1]:https://i.stack.imgur.com/Z53nF.png [2]:https://i.stack.imgur.com/QeRnw.png

【问题讨论】:

    标签: r ggplot2 ggplotly


    【解决方案1】:

    您的代码似乎缺少一些变量,因此我无法获得相同的图表来向您展示,但您的问题似乎最好使用说明性示例数据框来回答。 TL;DR - 使用 breaks= 分配图例中的键顺序。

    您的问题的答案在于了解如何使用scale_*_manual() 更改图例的各个方面:

    • labels= 使用它来更改每个图例键的外观(单词)。

    • values= 在您开始设置任何其他参数时是必需的。如果您提供命名向量或列表,您可以为与数据关联的基础因子的每个级别显式分配颜色。如果您提供颜色列表,它们将被分配根据图例中标签的顺序。请注意,它不是根据因子的级别分配的。

    • breaks= 使用此参数指示图例键出现的顺序

    示例如下:

    library(dplyr)
    library(tidyr)
    library(ggplot2)
    df <- data.frame(x=1:100, Low=rnorm(100,5,1.2),Med=rnorm(100,10,2),High=rnorm(100,15,0.8))
    df <- df %>% gather('Status','Values',-x)
    
    p <- ggplot(df, aes(Status,Values)) + geom_boxplot(aes(fill=Status), alpha=0.5)
    p + scale_fill_manual(values=c('red','blue','green'))
    

    df$Status 在 x 轴上出现的顺序由factor(df$Status) 中的levels= 的顺序决定。这不是您在问题中提出的问题,但最好记住。默认情况下,这似乎是按字母顺序决定的。

    图例条目同样按字母顺序排列,但这是因为顺序将默认为factor(df$Status) 中的级别顺序,用于离散值。因此,values= 的未命名颜色向量是根据图例中项目的顺序分配的。

    注意如果您使用 labels= 尝试将其恢复为“低、中、高”会发生什么:

    p + scale_fill_manual(labels=c('Low','Med','High'), values=c('red','blue','green'))
    

    现在您应该看到使用简单向量分配labels= 的危险。 labels= 参数只是重命名各个级别的每个标签......但顺序不会改变。如果我们想重命名关卡,更好的方法是向labels= 发送一个命名向量:

    p + scale_fill_manual(
      labels=c('Low'='Lowest','Med'='Medium','High'='Highest'),
      values=c('red','blue','green'))
    

    如果您想更改图例中项目的顺序,您可以使用breaks= 参数来实现。在这里,我将向您展示所有参数的组合:

    p + scale_fill_manual(
      labels=c('Low'='Lowest','Med'='Medium','High'='Highest'),
      values=c('red','blue','green'),
      breaks=c('Low','Med','High'))
    

    【讨论】:

    • 非常感谢您的解释!我将 Reddit 我的代码以确保它是可重现的!
    • 它可能只是缺少mylevels - 如果您添加它,我认为它可能会正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多