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
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