1

I'm trying to make a smooth curve but I don't know why is not working. This is my dataset

data.fam
###specnumber_f site  position
             23   MS  on
              9   MS  on
             11   CU  on
              9   CA  on
             21   CF  on
             17   ST  on
              6   AB  on
              4   AB  on
              8   AB  on
              3   FN off
              4   FN off
             14   RO off
              6   RO off
              7 SPSP off
              4 SPSP off
              3 SPSP off

I need that the x-axis follow this order of sites

lat.order <- factor(data.fam$site, levels=c("MS", "CU", "CA", "CF", "ST", "AB", "FN",
"RO", "SPSP")) 

Then, I tried this code but geom_smooth doesn't plot, I believe it's a simple answer by I couldn't solve it

ggplot(data.fam, aes(x=as.factor(lat.order), y=specnumber_f))+
  geom_point(aes(colour = factor(position)), size = 2)+
  geom_smooth()
3
  • 4
    Probably because the x variable is discrete. Try setting the group in geom_smooth() to -1 or something. Commented Aug 6, 2021 at 16:34
  • 2
    You get a "probably" answer because you did not provide a reproducible example of your problem stackoverflow.com/help/minimal-reproducible-example Commented Aug 6, 2021 at 18:48
  • OP, follow the suggestion of /u/teunbrand. Change geom_smooth() to be geom_smooth(aes(group=-1) and you'll get the line. Of course, your axis is still discrete, so it won't be a smooth line, but this way ggplot knows to connect the points. If you want a smooth line, you will need to make a new column that is continuous, then maybe use scale_x_continuous() to label your breaks. Commented Aug 8, 2021 at 12:57

1 Answer 1

1

OP. The reason your line doesn't show is due to you x axis values being discrete. In effect, ggplot2 does not know how to connect your data along the x axis, since with discrete data there is no obvious reason to connect along that axis.

There are two general solutions here. One is simple and gives you a line with hard edges, whereas the other is more involved, but you will get a line that has completely smooth edges.

Simple Solution: Not Smooth Line

To get a "not-smooth" line, all you need to do is tell ggplot2 that the points along the x axis are all connected in that dimension and that it should use the number value of the level to assign to the x axis. Without treating the scale numerically, there is no way to calculate a formula along that axis so this is necessary. Since the axis is still discrete in this case, there is no point that would make sense if it were in-between any two values along x, so the line you get is going to be angular (not-smooth). Thank @teunbrand for this solution:

ggplot(data.fam, aes(x=site, y=specnumber_f)) +
  geom_point() + geom_smooth(aes(group=-1))

enter image description here

Getting a Smooth Line

If you are aesthetically pleased with the simple solution, then it's the easiest so go with that. If you really wanted a smooth line, here's one way to do it. The basic idea is that we need to change your discrete axis into a continuous one. The problem is that data.fam$site is not continuous. Therefore, we need to basically map the values of data.fam$site to another column that is numeric, then use scale_x_continous() to label our axis with the correct names from data.fam$site.

First, we set the order of your axis labels aside:

lat.order.levels <- c("MS", "CU", "CA", "CF", "ST", "AB", "FN",
                      "RO", "SPSP")

Then, we make another data frame that will be used to map our continuous column (herein site_num) onto the original data frame, data.fam.

site.data <- data.frame(
  site = lat.order.levels,
  site_num = 1:length(lat.order.levels)
)

Finally, we merge the two frames, keeping all the points in data.fam. I create a new data.frame for this called df:

df <- dplyr::left_join(data.fam, site.data, by= "site")

For the plot, you assign the x aesthetic to site_num, and use lat.order.levels to label the axis via scale_x_continuous().

ggplot(df, aes(x=site_num, y=specnumber_f)) +
  geom_point() + geom_smooth() +
  scale_x_continuous(
    breaks=1:length(lat.order.levels),
    labels=lat.order.levels
  )

enter image description here

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

Comments

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.