41

I'm plotting ggplot with geom_point. The x-axis will be individuals' ID, and y-axis is variable A. How can I ggplot all and individual ID values on the x-axis without overlapping labels? ID may not be continuous.

df sample (actual rows are much longer)

> df
ID     A
1      4
2      12
3      45
5      1

Code for the plot:

ggplot(df, aes(x = ID, y = A)) + geom_point()

Above code has x-axis in intervals, but not presenting individual ID.

Thanks!

1

3 Answers 3

103

Is this what you're looking for?

ID <- 1:50
A <- runif(50,1,100)

df <- data.frame(ID,A)

ggplot(df, aes(x = ID, y = A)) + 
  geom_point() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  scale_x_continuous("ID", labels = as.character(ID), breaks = ID)

This will produce this image:

enter image description here

So you'll get a label for every ID-value. If you'd like to remove the gridlines (There are too much for my taste) you can remove them by adding theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())

EDIT: The easier way would be to just use ID as a factor for the plot. like this:

ggplot(df, aes(x = factor(ID), y = A)) + 
  geom_point() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  xlab("ID")

enter image description here

The advantage of this method is that you don't get empty spaces from missing IDs

EDIT2: Concerning your Problem with overlapping labels: I'm guessing it comes from a large number of IDs to be plotted. There are several ways we can deal with this. So lets say your plot looks like this:

enter image description here

One idea would be to hide every 3rd label from the x-axis by modifying the break argument of the axis:

ggplot(df, aes(x = factor(ID), y = A)) + 
  geom_point() + 
  scale_x_discrete(breaks = ID[c(T,F,F)]) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  xlab("ID")

which leads to this:

enter image description here

If hiding labels is not an option, you could split your plot into subplots.

df$group <- as.numeric(cut(df$ID, 4))

ggplot(df, aes(x = factor(ID), y = A)) + 
  geom_point() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) +
  xlab("ID") +
  facet_wrap(~group, ncol = 1, scales = "free_x")

which leads to this:

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

thanks! that's what I need. And how can I increase the space between the x labels like you did in the second plot? Mine's are overlapping.
why are your labels overlapping? I'm guessing you're trying to plot a lot of IDs. I've edited my answer and added some information, let me know if my ideas work for you
Fantastic! I had been looking for something like this everywhere!
0

This worked for me when ID is discrete and discontinuous:

df$ID <- as.character(df$ID)
xlab <- sort(unique(df$ID))
ggplot(df, aes(x= ID, y= A)) + geom_point() + scale_x_discrete(labels= xlab)

Comments

-1

Just add + xlim() and + ylim() to show the full x axis and y axis (i.e. to make the x axis and y axis start at zero).

Reproducible example

If this is your ggplot:

iris %>% 
  ggplot(aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_point() 

enter image description here

simply add these two lines to make the x and y axes start at zero:

iris %>% 
  ggplot(aes(x=Sepal.Length, y=Sepal.Width)) +
  geom_point() +     
  xlim(0, 8.2) +     # add this line for x axis limits
  ylim(0, 4.5)       # add this line for y axis limits

enter image description here

1 Comment

I guess this is not what the question was about

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.