0

I am trying to create a bar plot with a solid straight trendline but can't get the trendline to appear.

I am using the ggplot2 package and here is my current code for the bar plot:

library(ggplot2)

ggplot(mydf, aes(x=round, y=means, fill=round)) +
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2) + 
  geom_bar(stat="identity", color="black", position=position_dodge()) + 
  geom_errorbar(aes(ymin=means-se, ymax=means+se), width=.2, position=position_dodge(.9),) +
  theme_classic() + 
  xlab("Round") + 
  ylab("Bead Mass (g)") + 
  ggtitle("Verbal") + 
  theme(legend.position="none") + 
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2)

I'm not sure why the geom_smooth() section is not working. Any ideas? See graph for what the output looks like enter image description here

tjebo
  • 21,977
  • 7
  • 58
  • 94
Ben
  • 3
  • 1
  • 1
    Welcome to SO! You could try with setting the `group` aes, i.e. try `geom_smooth(aes(group = 1), method=lm, ...)`. For more help we need [a minimal reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) including a snippet of your data or some fake data best shared via `dput()`. – stefan Mar 07 '23 at 08:58

2 Answers2

0

Two things stop the smooth being plotted, the first is that the x axis appears to be a factor, so it needs to be converted to a numeric variabke, the second is that ggplot will automatically treat different fill (from a factor) as separate groups, so this needs to be overwritten for the smooth layer, giving:

library(ggplot2)

#Example data similar to the plot shown
mydf <- data.frame(round=factor(1:5), means=c(102, 75, 73, 95, 120), se=15)

ggplot(mydf, aes(x=as.numeric(round), y=means, fill=round)) +
   geom_bar(stat="identity", color="black", position=position_dodge()) + 
  geom_errorbar(aes(ymin=means-se, ymax=means+se), width=.2, position=position_dodge(.9),) +
  theme_classic() + 
  xlab("Round") + 
  ylab("Bead Mass (g)") + 
  ggtitle("Verbal") + 
  theme(legend.position="none") + 
  geom_smooth(aes(fill=NULL),  method=lm, se=FALSE, col="black", linewidth=2)

Example output

Miff
  • 7,486
  • 20
  • 20
0

The discrete fill scale of your plot shows that the round variable you use for x and fill is not numeric, preventing geom_smooth from working properly.

Reproduction of the issue

library(dplyr)
library(ggplot2)

mydf <- iris %>%
  mutate(round = as.character(as.numeric(as.factor(Species)))) %>%
  group_by(round) %>% 
  summarise(means = mean(Sepal.Length),
            se = sd(Sepal.Length)/sqrt(n())) %>%
  ungroup()

mydf
# A tibble: 3 x 3
  round means     se
  <chr> <dbl>  <dbl>
1 1      5.01 0.0498
2 2      5.94 0.0730
3 3      6.59 0.0899
ggplot(mydf, aes(x=round, y=means, fill=round)) +
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2) + 
  geom_bar(stat="identity", color="black", position=position_dodge()) + 
  geom_errorbar(aes(ymin=means-se, ymax=means+se), width=.2, position=position_dodge(.9),) +
  theme_classic() + 
  xlab("Round") + 
  ylab("Bead Mass (g)") + 
  ggtitle("Verbal") + 
  theme(legend.position="none") + 
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2)

enter image description here

Solution

  • Convert the x variable to numeric in the global aes and remove the fill aesthetics
  • Specify the fill aestethics only in the geom_bar aes
ggplot(mydf, aes(x=as.numeric(round), y=means)) +
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2) + 
  geom_bar(aes(fill = round), stat="identity", color="black", position=position_dodge()) + 
  geom_errorbar(aes(ymin=means-se, ymax=means+se), width=.2, position=position_dodge(.9),) +
  theme_classic() + 
  xlab("Round") + 
  ylab("Bead Mass (g)") + 
  ggtitle("Verbal") + 
  theme(legend.position="none") + 
  geom_smooth(method=lm, se=FALSE, col="black", linewidth=2)

enter image description here

L--
  • 565
  • 1
  • 12