ggplot2分组的条形图,带有2个数据集

时间:2019-08-08 12:02:01

标签: r ggplot2 bar-chart

我有两个要绘制的data.frames和一个分组的条形图。

第一个数据框是一个堆叠的条形图,具有多种颜色,左侧是相应的轴。

第二个数据框是单个条形图,仅具有一种颜色,相应的轴在右侧。

下图说明了我的目标:

enter image description here

这是我的数据集和失败的尝试:

library(ggplot2)
library(dplyr)
df1 <- structure(list(day = structure(c(1L, 1L, 1L, 1L), .Label = "2019-01-29", class = "factor"), 
                      streckenabschn = c("something", "something", "something", "something"), 
                      variable = c("a", "b", "c", "d"), 
                      value = c(0, 0, 2, 8)), 
                 row.names = c(NA, -4L), class = "data.frame")

df2 <- structure(list(day = structure(1:2, .Label = c("2015-12-25", "2019-01-29"), class = "factor"), 
                      streckenabschn = c("something", "something"), 
                      variable = c("x", "x"), value = c(0.6, 3.471875)), 
                 row.names = 1:2, class = "data.frame")


cbPalette <- c('#3652a3', '#60a0df', '#b7dbff', '#dd0000', "gray")
legendLabels <- c("a", "b", "c", "d", "x")
ggplot() +
  geom_bar(data = df1, aes(x=day, y=value, fill = variable),
           stat = "identity", width=0.2) +
  geom_bar(data = df2, aes(x=day, y=value, fill = variable),
           stat = "identity", width=0.2, position = position_dodge(width=0.5)) +
  scale_fill_manual(name="", values=cbPalette, labels=legendLabels) +
  scale_y_continuous(sec.axis = sec_axis(~., name = "Axis 2")) +
  guides(fill = guide_legend("Legend", nrow = 2, ncol=4, byrow = T)) +
  theme(legend.position = "top") + ylab("Axis 1")

我的问题:

  • 我如何堆叠1个条形图,而另一个 “躲闪”?
  • 如何定义“ Axis 2”标签并中断 对应数据,因为我不能使用转换公式?

我在做错什么以及如何正确做?

1 个答案:

答案 0 :(得分:1)

您可以将两个数据集合并为一个,对x位置进行一些手动预处理,然后绘制:

library(dplyr)
w = 0.2
bind_rows(df1, df2, .id="src") %>% 
  mutate(x0 = as.integer(factor(day)),
         dx = c(-w/2, w/2)[as.integer(factor(src))]) %>% 
  ggplot(aes(day, value)) +
  geom_blank(aes(x = day, y = value)) + # useful to get correct labelling of axes
  geom_bar(aes(x = x0 + dx, y = value, fill = variable),
           stat = "identity", width = w) +
  scale_fill_manual(name = "", values = cbPalette, labels = legendLabels) +
  guides(fill = guide_legend(nrow = 2, ncol = 4, byrow = TRUE)) +
  theme_light() + theme(legend.position = "top")

次级轴

在ggplot中不建议使用辅助垂直轴,但如果确实需要,可以指定自定义转换函数(线性缩放)并使用sec_axis

首先定义两个缩放函数:

# Functions scaling ticks and values for using secondary scale
# !! This is visually OK but lacks interpretability. 
# Preferrable to use business-derived hardcoded ratio !!

# Helper function
get_max_height = function(df) {
  df %>% 
    group_by(day) %>% 
    summarize(h = sum(value)) %>% 
    with(max(h))
}
ratio_1_2 = get_max_height(df1) / get_max_height(df2)

# from scale of df2 to scale of df1:
trans_values = function(v2) {
  v2 * ratio_1_2  
}
# from scale of df1 to scale of df2:
trans_ticks = function(v1) {
  v1 / ratio_1_2
}

然后在数据框和图形轴中使用它们:

bind_rows(
  df1 %>% mutate(day = as.character(day), y = value),
  df2 %>% mutate(day = as.character(day), y = trans_values(value)),
  .id="src"
  ) %>% 
  mutate(
    x0 = as.integer(factor(day)),
    dx = c(-w/2, w/2)[as.integer(factor(src))]
  ) %>% 
  ggplot() +
  geom_blank(aes(day)) +
  geom_bar(aes(x0 + dx, y, fill = variable),
           stat = "identity", width = w) +
  scale_y_continuous("Values 1", sec.axis = sec_axis(trans_ticks, "Values 2")) +
  scale_fill_manual(name = "", values = cbPalette, labels = legendLabels) +
  guides(fill = guide_legend(nrow = 2, ncol = 4, byrow = TRUE)) +
  theme_light() + theme(legend.position = "top")
相关问题