【问题标题】:如何整齐地对齐堆叠的条形图标签,条形图的每一侧都有不同的对齐方式?
【发布时间】:2022-01-21 15:23:43
【问题描述】:

我的标签与堆叠条形图的每一侧大致对齐。问题是它们看起来像一团糟,因为它们在栏的两边都不是左右对齐的。我该如何解决这个问题,让他们看起来很专业?

df3 <- data.frame(
  Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
  Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
)

# Sort order
level_order <- df3 %>% 
  arrange(desc(Amount))

ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) + 
               geom_bar(position="stack", stat="identity", width = 0.55) +
               scale_fill_brewer(palette = "Blues", direction = -1) +
               theme_void() +
               geom_text(aes(label = paste0("$", Amount)),
                         position = position_stack(vjust = 0.5),
                         hjust = -3.1,
                         size = 5) +
               geom_text(aes(label = Label),
                         position = position_stack(vjust = 0.5),
                         hjust = 5,
                         size = 5) +
               theme(legend.position = "none") +
               theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
               ggtitle("Food Costs by Reindeer")

【问题讨论】:

  • 你能否把问题说得更清楚些:你想让左手标签左对齐,右手标签右对齐吗?
  • 我们从中学到了什么?鲁道夫是真正的交易!

标签: r ggplot2 data-visualization


【解决方案1】:

hjust 确定文本对齐方式(0 为左对齐,1 为右对齐)。此时你的geom_text 的 x 坐标默认为 1,因此更改它会更改文本的位置。

ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) + 
  geom_bar(position="stack", stat="identity", width = 0.55) +
  scale_fill_brewer(palette = "Blues", direction = -1) +
  theme_void() +
  geom_text(aes(x=0.6, label = paste0("$", Amount)),
            position = position_stack(vjust = 0.5),
            hjust = 0.5,
            size = 5) +
  geom_text(aes(x=1.4, label = Label),
            position = position_stack(vjust = 0.5),
            hjust = 0.5,
            size = 5) +
  theme(legend.position = "none") +
  theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
  ggtitle("Food Costs by Reindeer")

【讨论】:

    【解决方案2】:

    尝试在对geom_text 的调用中修复x 坐标并管理与hjust 的对齐...

    df3 <- data.frame(
      Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
      Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
    )
    
    
    library(ggplot2)
    library(dplyr)
    library(forcats)
    
    level_order <- df3 %>% 
      arrange(desc(Amount))
    
    ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) + 
      geom_bar(position="stack", stat="identity", width = 0.55) +
      scale_fill_brewer(palette = "Blues", direction = -1) +
      theme_void() +
      geom_text(aes(x = 1.3, label = paste0("$", Amount)),
                position = position_stack(vjust = 0.5),
                hjust = 0,
                size = 5) +
      geom_text(aes(x = 0.6, label = Label),
                position = position_stack(vjust = 0.5),
                hjust = 0,
                size = 5) +
      theme(legend.position = "none") +
      theme(plot.title = element_text(size = 50, hjust = .5, vjust = 0)) +
      ggtitle("Food Costs by Reindeer")
    

    reprex package (v2.0.1) 于 2021-12-19 创建

    【讨论】:

    • 以您的答案为起点,我使用了 hjust 函数来进行调整,并使用了我忘记定位标签的 x 参数。完美的!我会在答案中展示它的样子。
    【解决方案3】:

    你也可以把 hjust 作为一种审美。为此,您需要将标签准备为单独的数据框。然后,您只需调用geom_text一次。我并不是说这一定更好,只是指出这是可能的。代码中还有一些 cmets,以及一些常见的陷阱。

    library(tidyverse)
    df3 <- data.frame(
      Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
      Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
    ) %>% 
      ## arrange step here
      arrange(desc(Amount)) 
    
    ## I like to prepare the data outside ggplot
    label_df <- df3 %>% 
      mutate(Amount_lab = paste0("$", Amount)) %>%
      pivot_longer(-Amount) %>%
    ## this adds a column for your adjustment, and the x position compared with the central column
      mutate(hjust = rep(0:1, nrow(.)/2), 
             x = rep(c(1.21, .79), nrow(.)/2))
    
    ggplot(mapping = aes(y = Amount)) + 
      ## geom_col is geom_bar(stat = "identity"), stack is default, so you can omit it
      ## call data in the geom layers
      ## set x to 1
      ## width = .4 so it matches your selected x from above
      geom_col(data = df3, aes(x = 1, fill=fct_inorder(Label)), width = .4) +
      scale_fill_brewer(palette = "Blues", direction = -1) +
      ## need to reverse both y and value, weirdly 
      geom_text(data = label_df, aes(x, y = rev(Amount), label = rev(value), 
    ## this is the main trick
      hjust = hjust),
      position = position_stack(vjust = 0.5) ) +
      ## sadly, need to turn clip off
      coord_cartesian(clip = "off") +
      theme_void() +
    ## call theme only once!!
      theme(legend.position = "none",
            plot.title = element_text(size = 20, hjust = .5, vjust = 0),
            ## you need to add a margin 
            plot.margin = margin(r = .6, l = .6, unit = "in")) +
      ggtitle("Food Costs by Reindeer")
    

    reprex package (v2.0.1) 于 2021-12-20 创建

    【讨论】:

      【解决方案4】:

      使用上面彼得的回答(提醒我我忘记存在的“x”位置参数),这是得到我想要的最终修复。 hjust = 0 是左对齐,hjust = 1 是右对齐。

      library(tidyverse)
      library(grid)
      
      df3 <- data.frame(
        Label = c("Dasher", "Dancer", "Comet", "Cupid", "Prancer", "Blitzen", "Rudolph"),
        Amount = c(650.01, 601.01, 340.05, 330.20, 260.01, 250.80, 10.10)
      )
      
      # Sort order
      level_order <- df3 %>% 
        arrange(desc(Amount))
      
      ggplot(level_order, aes(fill=fct_inorder(Label), y=Amount, x="")) + 
                     geom_bar(position="stack", stat="identity", width = 0.55) +
                     scale_fill_brewer(palette = "Blues", direction = -1) +
                     theme_void() +
                     geom_text(aes(x = 1.3, label = paste0("$", Amount)),
                               position = position_stack(vjust = 0.5),
                               hjust = 0,
                               size = 5) +
                     geom_text(aes(x = 0.7, label = Label),
                               position = position_stack(vjust = 0.5),
                               hjust = 1,
                               size = 5) +
                     theme(legend.position = "none",
                           plot.margin = unit(c(0,0,2,0), "cm"))
      grid.text("Food Costs by Reindeer", x = unit(0.5, "npc"), y = unit(0, "npc"),
                vjust = -0.5, gp = gpar(cex=4))
      

      【讨论】:

        猜你喜欢
        • 2014-03-10
        • 2014-05-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-29
        • 1970-01-01
        • 1970-01-01
        • 2021-09-05
        • 1970-01-01
        相关资源
        最近更新 更多