2

I need to plot a MDS with vectors showing changes in abundance for my species. I need the plot with just vectors

This is my data with abundance for each species and code

library(vegan)

A <- c(54.67, 37.67, 19.33, 0, 6, 8, 84.67, 0,0,0,0,0,0,0)
B <- c(3.67, 10.33, 32.67, 5.33, 20.33, 5.33, 4.67, 3, 4, 0.01, 0.1, 0, 5, 0)
C <- c(10, 1.67, 2.67, 1.67, 11.33, 1.33, 1, 2, 2.77, 0, 0.02, 1,3,0)
D <- c(1,10.33, 2.33, 28.33, 29.33, 4.33, 21, 6.97, 4.47, 0, 0.16, 11, 4,0)
df <- cbind(A, B, C, D)
row.names(df) <- c('B_2016', 'Emb_2016', 'Fes_2016', 'Ku_2016', 'Ra_2016', 'Ud_2016',
                   'Ve_2016', 'Ba_2017', 'Emb_2017', 'Fes_2017', 'Ku_2017', 'Ra_2017', 
                   'Ud_2017', 'Ve_2017')

mds <- metaMDS(df, distance='bray')

I am using these codes to create a dataframe

mdspoints <- data.frame(scores(mds))
mdsvectors <- data.frame(mds$species)

and this is the code I am using to graph

g <- ggplot(data = mds, aes(MDS1, MDS2)) + 
  geom_segment(data = mdsvectors, aes(x=0, xend=MDS1, y=0, yend=MDS2),
               arrow = arrow(length = unit(0.5, "cm")),
               colour="grey", inherit_aes = FALSE) + 
  geom_text(data=mdspoints, aes(x=MDS1, y=MDS2, label=species), size=5)

but I cannot graph anything and get an error (Error: ggplot2 doesn't know how to deal with data of class metaMDS/monoMDS).

I would like something like this

Thank you

Claire
  • 79
  • 1
  • 8
  • 2
    Uh, the error you get would be relevant. – l'L'l Sep 01 '18 at 22:25
  • how can I create the right plot? – Claire Sep 01 '18 at 22:43
  • Well, I would start by explaining the error you get as said before. – l'L'l Sep 01 '18 at 22:44
  • small tipp for formatting your questions: https://stackoverflow.com/help/formatting. Also it's always good to refer to the package which you need. (i.e. add `library(vegan)` to your code. Or tag it , see my edit. – tjebo Sep 01 '18 at 22:46
  • now to your question itself. as @I'L'I said - it would have been really helpful if you would have posted your error message. Now when looking this up: `Error: data must be a data frame, etc...`. This is pretty obvious, what is the problem. `mds` is a list. You need a data frame – tjebo Sep 01 '18 at 22:53
  • Have you tried following [this procedure](https://chrischizinski.github.io/rstats/vegan-ggplot2/)? Is this what you're after? – Roman Luštrik Sep 01 '18 at 22:56
  • yes thanks, it doesn't really create the graph I need – Claire Sep 02 '18 at 01:36
  • 1
    It doesn't make much sense to show the species with a vector from the origin in an NMDS as they are calculated with a weighted average. – Richard Telford Sep 02 '18 at 09:27
  • 2
    Your graph shows something completely different than what you say you want to have. Your code tries to draw arrows from the origin to the species points (that you should not do like @RichardTelford tells you), but the graph shows arrows from varying points. What do you like to show? Change in points or distances and directions from the origin? – Jari Oksanen Sep 03 '18 at 08:38
  • Thank you, yes you are absolutely right, this is not what I want it to show. I want to show that my species abundance changed from one year to another in my sites, and the arrow should connect the before–after pairs of data points for each site to show changes in species composition – Claire Sep 04 '18 at 11:56
  • yes change in points and directions from the origin – Claire Sep 04 '18 at 12:05

1 Answers1

3

I'm not sure exactly what you are aiming for, based on your code, but here are some things you may want to take note.

Point 1: Don't put anything in the top level ggplot() call, unless you want the subsequent layers to inherit it.

Instead of:

g <- ggplot(data = mds, aes(MDS1, MDS2)) + 

Use:

g <- ggplot() + 

You've already created data frames mdspoints & mdsvectors, and none of your geom layers requires anything from mds. You really don't need it here. But since it is there, ggplot will check it.

Had mds been a data frame, it would pass ggplot's check, & be ignored since the subsequent layers don't need it. However, it is metaMDS / monoMDS object, causing ggplot to throw the error you saw.

Point 2: Check if your data frames are what you expected.

Your code includes the following line:

  geom_text(data=mdspoints, aes(x=MDS1, y=MDS2, label=species), size=5)

This tells ggplot that for plotting labels, it should look at the mdspoints data frame, and search for variables named MDS1 / MDS2 / species.

This is what was actually created from mdspoints <- data.frame(scores(mds)):

> mdspoints
             NMDS1         NMDS2
B_2016   -141.6526 -6.290613e-01
Emb_2016 -141.8424 -3.280861e-01
Fes_2016 -142.1144 -4.456856e-01
Ku_2016  -141.8335  3.674413e-01
Ra_2016  -141.8977  2.283486e-02
Ud_2016  -141.8824 -1.480702e-01
Ve_2016  -141.5302 -3.732303e-01
Ba_2017  -141.9265  2.233302e-01
Emb_2017 -141.9695  1.210940e-01
Fes_2017 -140.6462  1.430899e-01
Ku_2017  -141.8616  2.216499e-01
Ra_2017  -141.7638  7.116520e-01
Ud_2017  -142.0109  1.130730e-01
Ve_2017  1842.9317 -3.167902e-05

So, NMDS1 / NMDS2 instead of MDS1 / MDS2, and no column name for "species". Are the row names corresponding to species? I'm not sure as I don't use the vegan package myself, but a quick look at the help file for its scores() function uncovers the following:

## Default S3 method:
scores(x, choices, display=c("sites", "species"), ...)

Which suggests that this may be the scores for sites, rather than species. If that understanding is correct, you'll want to specify "species" when you create mdspoints, and manually create the species column from row names:

mdspoints <- data.frame(scores(mds, "species"))
mdspoints$species <- row.names(mdspoints)

Result

Here's what the plot could look like:

ggplot() + 
  geom_segment(data = mdsvectors, aes(x=0, xend=MDS1, y=0, yend=MDS2),
               arrow = arrow(length = unit(0.5, "cm")),
               colour="grey") +
  geom_text(data=mdspoints, aes(x=NMDS1, y=NMDS2, label=species), size=5) +
  labs(x = "NMDS1", y = "NMDS2") + # add axis labels
  theme_classic()                  # use a white theme for better contrast

plot

Z.Lin
  • 28,055
  • 6
  • 54
  • 94
  • 1
    Another one of those fantastic, comprehensive Z.Lin answers :) – tjebo Sep 02 '18 at 08:17
  • 1
    You should **always** have equal aspect ratio in ordination plots. You can achieve this adding `+ coord_equal()` or `+ coord_fixed()` in your graph. When you do this, you see that you only have one real axis in your graph and the arrows make little sense (it seems that NMDS2 shows round-off errors in input data). – Jari Oksanen Sep 03 '18 at 08:41
  • @JariOksanen Thank you, so what code should I use..I need to create arrows which connect the 2016–2017 pairs of data points for each location to show changes in composition of species A-B-C-D on my sites – Claire Sep 06 '18 at 12:30