Search code examples
rggplot2axis-labelsgeom-col

Change axis breaks/limits of ggplot with geom_col


I am having problems with changing the axis ticks in a barplot. I am fairly new in using ggplot so the answer might be very obvious.

Here is some data (yes it is strange, but designed to mimic the original dataset I have, which I am not allowed to share):

lab='this is just a very long example text and it will be longer and longer and longer and longer and longer and longer and longer and longer and longer and end'
number=1:20
n=unlist(lapply(number,paste,value=lab))
a=round(runif(n=20,min=-48000,max=-40000))
b=round(runif(n=20,min=-48000,max=-40000))
c=round(runif(n=20,min=-48000,max=-40000))
d=data.frame(cbind(n,a,b,c))
df=pivot_longer(d,cols=c('a','b','c'))
l1=round(as.numeric(min(df$value))/1000 )*1000+1000
l2=round(as.numeric(max(df$value))/1000 )*1000-1000
lim=seq(from=l1,to=l2,by=-1000)  
colScale <- scale_fill_manual(name = "n",values = c(rainbow(nrow(df)/3)))

from which I create a barplot

p1=ggplot(df, aes(name, value, fill = as.factor(n))) +
  geom_col(position = "dodge",colour='black') +
  #scale_y_continuous(breaks = lim , labels = as.character(lim)) +
  coord_flip() +
  theme_bw() + 
  theme(axis.text.x=element_text(angle=90),axis.title.x=element_text(face='bold')) +
  theme(axis.text.y=element_text(angle=90,size=15)) +
  theme(legend.title=element_blank()) +
  labs(x = "",y="test") +
  colScale +
  guides(fill=guide_legend(ncol=1)) +
  ggtitle('something') +
  theme(plot.title = element_text(hjust = 0.5,size=20)) 

which is this

that is basically working as I wanted, but the scaling of the x-axis is very unpleasant. What I want instead is an axis, where the breaks and labels are equal to the vector 'lim'. What I understood was that it should be possible to do this by scaling the respective axis as in the commented line. But when I'm trying this I get the error 'Discrete value supplied to continuous scale'. I tried to change the scale to 'scale_y_discrete' but then the ticks disappear completely. I tried everything I could find but nothing worked, so what is wrong?

Based on the answers I changed the plot definition to:

p1=ggplot(df, aes(name, as.numeric(value), fill = as.factor(n))) +
  geom_col(position = "dodge",colour='black') +
  scale_y_continuous(breaks = lim , labels = as.character(lim)) +
  coord_flip() +
  theme_bw() + 
  theme(axis.text.x=element_text(angle=90),axis.title.x=element_text(face='bold')) +
  theme(axis.text.y=element_text(angle=90,size=15)) +
  theme(legend.title=element_blank()) +
  labs(x = "",y="test") +
  colScale +
  guides(fill=guide_legend(ncol=1)) +
  ggtitle('something') +
  theme(plot.title = element_text(hjust = 0.5,size=20)) 

which produced this plot

now I am able to change the axis ticks, but the plot looks nothing like the first one. My goal is to keep the look, meaning showing only the top part of the bars.


Solution

  • I'd suggest converting value to as.numeric (preferably before ggplot, but you can do it within, like below) and using coord_cartesian to specify the "view window". You also might find it simpler to specify your axes in the order you want them, rather than using coord_flip, which is mostly unnecessary since ggplot 3.3.0.

    ggplot(df, aes(as.numeric(value), name, fill = as.factor(n))) +
      geom_col(position = "dodge",colour='black') +
      scale_x_continuous(breaks = lim , labels = as.character(lim)) +
      coord_cartesian(xlim = c(min(as.numeric(df$value)), max(as.numeric(df$value)))) 
    # Theming after this up to you