【问题标题】:Overlaying barplot with line graphs using ggplot2使用 ggplot2 用折线图覆盖条形图
【发布时间】:2017-08-27 19:34:39
【问题描述】:

我的问题与herehere 发布的问题类似。

我正在ggplot 中创建一个图表,其中我有一个条形图,然后想要覆盖多个折线图。出于这个问题的目的,我已经为两个条形图(一个包括所有年份(2007-2015)和两个特定年份(2007 和 2015))复制了我的代码,但最终我将覆盖 10 个不同年份的数据。使用的数据可以在here找到。

library(dplyr)
library(tidyr)
library(gridExtra)
library(ggplot2)

overallpierc<-data[(data$item=="piercing"),]

overp<-overallpierc %>%
  group_by(age) %>% 
  count(sex) %>% 
  ungroup %>% 
  mutate(age = factor(age)) %>%
  complete(age, sex, fill = list(n = 0)) %>% 
  ggplot(aes(age, n)) + geom_col(aes(fill = sex), position = "dodge") +
    theme_classic() + 
    scale_fill_manual(values=c("#000000", "#CCCCCC"), name = "Sex") + 
    labs(x = "Age", y = "Number of observations") +   
    theme(legend.position=c(0.4,0.8),
    plot.title = element_text(size = 10),
    legend.title=element_text(size=15),
    axis.title=element_text(size=15),
    legend.key.size = unit(1.13, "cm"),
    legend.direction="vertical",
    legend.text=element_text(size=15))

p07<-data[(data$yy=="2007") & (data$item=="piercing"),]
summary(p07)

subp07<-p07 %>%  
  group_by(age) %>% 
  count(sex) %>% 
  ungroup %>% 
  mutate(age = factor(age)) %>%
  complete(age, sex, fill = list(n = 0)) %>% 
  ggplot(aes(age, n)) + geom_col(aes(fill = sex), position = "dodge") +
    theme_classic() + 
    scale_fill_manual(values=c("#000000", "#CCCCCC"), name = "Sex") + 
    labs(x = "Age", y = "Number of observations") +   
    theme(legend.position=c(0.4,0.8),
    plot.title = element_text(size = 10),
    legend.title=element_text(size=15),
    axis.title=element_text(size=15),
    legend.key.size = unit(1.13, "cm"),
    legend.direction="vertical",
    legend.text=element_text(size=15))

p15<-data[(data$yy=="2015") & (data$item=="piercing"),]

subp15<-p15 %>% 
  group_by(age) %>% 
  count(sex) %>% 
  ungroup %>% 
  mutate(age = factor(age)) %>%
  complete(age, sex, fill = list(n = 0)) %>% 
  ggplot(aes(age, n)) + geom_col(aes(fill = sex), position = "dodge") +
    theme_classic() + 
    scale_fill_manual(values=c("#000000", "#CCCCCC"), name = "Sex") + 
    labs(x = "Age", y = "Number of observations") +   
    theme(legend.position=c(0.4,0.8),
    plot.title = element_text(size = 10),
    legend.title=element_text(size=15),
    axis.title=element_text(size=15),
    legend.key.size = unit(1.13, "cm"),
    legend.direction="vertical",
    legend.text=element_text(size=15))

grid.arrange(overp, subp07, subp15)

我发布的代码给了我下图。

我要做的是在总频率的条形图顶部绘制 2007 年和 2015 年女性的频率以及 2007 年和 2015 年男性的频率(这也反映在图例中)。有没有办法在R 中使用ggplot2 做到这一点?

更新:我尝试使用 geom_smoothgeom_line 函数将这些行添加到我的 ggplot 中,如 cmets 中的建议以及其他用户问题的解决方案,但我得到了以下错误:

错误:提供给连续刻度的离散值

我为要绘制的子集创建了一个新数据框:

df<-data.frame(age=c(15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,40,50,60), val=c(0,5,13,77,70,106,62,51,46,27,46,16,22,16,14,48,21, 3,4))

然后将其添加到ggplot代码中:

overallpierc %>%
  filter(age != "15") %>% 
  group_by(age) %>% 
  count(sex) %>% 
  ungroup %>% 
  mutate(age = factor(age)) %>%
  complete(age, sex, fill = list(n = 0)) %>% 
  ggplot(aes(age, n)) +     
    geom_line(data=df,aes(x=as.numeric(age),y=val),colour="blue") +
    geom_col(aes(fill = sex), position = "dodge") +
    theme_classic() + 
    scale_fill_manual(values=c("#000000", "#CCCCCC"), name = "Sex") + 
    labs(x = "Age", y = "Number of observations") +   
    theme(legend.position=c(0.4,0.8),
    plot.title = element_text(size = 10),
    legend.title=element_text(size=15),
    axis.title=element_text(size=15),
    legend.key.size = unit(1.13, "cm"),
    legend.direction="vertical",
    legend.text=element_text(size=15))

Others也遇到过类似问题,使用as.numeric解决问题。但是,出于绘图的目的,需要将年龄视为一个因素。

【问题讨论】:

  • 你能简单地将 geom_smooth 添加到你的 ggplot 基于一个数据框,每个年龄的值是观察的数量吗?
  • 是的,但我希望学习如何编写更复杂的解决方案,而不是每次都必须创建一个单独的数据框,因为我在我的论文中一直遇到这个问题。
  • 我的论文也遇到了类似的问题,我定义了一个对数据帧进行操作并生成所需结果数据帧的函数。在调用 ggplot 组件时,我将 data 参数设置为我的数据框的函数,即 + geom_smooth(data=aggregatingFunction(df),aes ...)
  • 您会考虑使用堆叠条吗?这将在同一个栏中按性别和总频率为您提供频率。然后你只需按年分面。如果这听起来有用,我会发布一个示例。
  • @BlunderingEcologist 看着 stackoverflow.com/questions/16350720/… 我可能会建议:geom_point(data=fun(data),aes(x=age, y=nObs, group=1),stat='summary', fun.y=sum) + stat_summary(fun.y=sum, geom="line")

标签: r plot ggplot2 overlay


【解决方案1】:

根据我们在 cmets 中的讨论,让我们尝试堆叠条形和刻面。我认为它有效,但您可以自己决定。

堆叠条的优点是在同一条中显示比例和总数。为了比较年份,刻面网格将年份排列成行,因此眼睛可以向下扫描以比较不同年份的相同年龄。请注意,我在这里将年龄作为一个连续变量,而不是一个因素。

library(dplyr)
library(ggplot2)
data30g %>% 
  count(yy, sex, age) %>% 
  ggplot(aes(age, n)) + 
    geom_col(aes(fill = sex)) + 
    facet_grid(yy ~ .) + 
    theme_bw() + 
    scale_fill_manual(values = c("#000000", "#cccccc"))

不错 - 例如,随着时间的推移,我可以立即看到 30 岁时的总人数和女性人数都在增加,但可能有点小而且拥挤。

我们可以使用分面环绕而不是网格来使条形更清晰,但代价是跨年的快速视觉比较。

data30g %>% 
  count(yy, sex, age) %>% 
  ggplot(aes(age, n)) + 
    geom_col(aes(fill = sex)) + 
    facet_wrap(~yy, ncol = 2) + 
    theme_bw() + 
    scale_fill_manual(values = c("#000000", "#cccccc"))

还有一个例子没有解决您在总计数或条形图方面的问题 - 但我认为它可能很有趣。这段代码生成了一个“热图”风格的绘图,它不适合定量比较,但有时可以快速给出有趣特征的视觉印象。例如,我认为这表明 2014 年 20 岁的女性人数最多。

data30g %>% 
  count(yy, sex, age) %>% 
  ggplot(aes(factor(age), yy)) + 
    geom_tile(aes(fill = n)) + 
    facet_grid(sex ~ .) + 
    scale_fill_gradient2() + 
    scale_y_reverse(breaks = 2006:2015) + 
    labs(x = "age", y = "Year")

编辑:

根据 cmets 中的进一步讨论,这里有一种将年龄作为一个因素的方法,使用条形表示性别,叠加一条线表示总数并按年份划分。

overallpierc %>% 
  count(yy, sex, age) %>% 
  ggplot() + 
    geom_col(aes(factor(age), n, fill = sex), position = "dodge") +
    stat_summary(aes(factor(age), n), fun.y = "sum", geom = "line", group = 1) + 
  facet_grid(yy ~ .)

【讨论】:

  • 这并不是我想要达到的目标,但如果无法使用ggplot2 将多个折线图叠加到条形图上,这可能就足够了。感谢您的帮助!
  • 当我将age 变量强制为一个因子而不是数字时,我在尝试使用geom_smoothgeom_line 函数添加其他行时遇到问题。您可能知道解决此问题的方法吗? (我在上面更新了我的问题。)
  • 我认为问题在于您在代码的 geom_line() 部分中将 age 更改为数字,但在 ggplot() 部分中没有。
  • 是的,我想这一定是个问题。但是,我试图将age 作为ggplot() 部分中的一个因素,因为我不想在 30、40、50 和 60 之间有大空间。但是,age 似乎需要numericgeom_line() 部分。有没有办法解决这个问题?也就是说,当agenumeric 时,不会出现30、40、50 和60 之间的那些大空间?
  • 在您的新代码示例中,M + F 的总和由堆叠条的总高度给出。我不清楚为什么需要一条线。但是:根据您的原始问题,我已经使用一些代码编辑了我的原始答案,这些代码使用stat_summary 覆盖条上的线条。就我个人而言,我不认为条形图上的线条是一种很好的可视化技术。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
相关资源
最近更新 更多