3
votes

I want to plot a NMDS in R using multiple variables. I've already used size, shape and colour in geom_point. But I have another variable, so I included it in geom_text as numerical values, the problem is that I need to show what each number is in another legend. Is it possible to do it without changing the size,shape and colour legends?

Here's what I've tried

data1<-data.frame("Replicas" = c(1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3),
 "Part" = c("leg","leg","leg","arm","arm","arm","leg","leg","leg","arm","arm","arm","leg","leg","leg","arm","arm","arm","leg","leg","leg","arm","arm","arm"),
 "Species" = c("Spc1","Spc1","Spc1","Spc1","Spc1","Spc1","Spc2","Spc2","Spc2","Spc2","Spc2","Spc2","Spc3","Spc3","Spc3","Spc3","Spc3","Spc3","Spc4","Spc4","Spc4","Spc4","Spc4","Spc4"),
 "Habitat" = c("Cali","Cali","Cali","Cali","Cali","Cali","Delhi","Delhi","Delhi","Delhi","Delhi","Delhi","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji","Fiji"),
 "NMDS1" = c(-0.556,-0.001,-0.074,-0.352,-0.019,0.111,-0.235,-0.663,-0.34,-0.39,-0.41,-0.669,0.176,0.038,-0.038,0.158,-0.177,-0.19,0.462,0.496,0.348,0.472,0.502,0.42),               "NMDS2" = c(-0.085,0.035,0.134,-0.124,0.055,0.064,0.22,-0.133,0.061,0.285,-0.082,-0.425,0.686,0.587,0.494,0.46,0.29,0.309,0.183,0.16,-0.242,0.1,-0.067,-0.339)
)
data2 <- as.integer(as.factor(data1$Habitat)) #To assign numerical values to each factor included in Habitat    
ggplot(data1, aes(NMDS1, NMDS2)) + 
 geom_point(aes(colour=factor(data1$Part), size=factor(data1$Replicas), shape=factor(data1$Species))) + 
 geom_text(aes(x=NMDS1,y=NMDS2,label=data2))

enter image description here

I want to include "Habitat" in the legend box, showing that 1 is Cali, 2 Delhi and 3 Fiji. Please,can someone help me?

1
Why not just write the species text instead of a numeric code?cory
Because the real data has many text characters and even if I use check_overlap = TRUE many points won't have the label I wantCyndi Kaulitz

1 Answers

5
votes

Below is a hack to get a text legend. First, some changes to your code:

  • The data frame name shouldn't be restated within aes. Just the bare column names should be used.
  • I've created a hab.num column in data2, rather than having a separate vector with the numbers. Using a separate vector is dangerous, because it breaks the mapping of columns from a given data frame to the various plot aesthetics. It might "work" in a particular situation, but it's brittle and prone to error.
  • The data.frame function automatically converts character columns to factor (unless you add the argument stringsAsFactors=FALSE), so there's no need to convert those columns to factor within the call to ggplot.

Okay, back to the problem at hand: We'll map hab.num to the fill aesthetic, since we're not using fill for anything else. That will create a legend. Then we'll set the legend labels to the desired values and we'll get rid of the point markers in the fill legend, because we just want text labels.

library(tidyverse)

data1 = data1 %>% 
  mutate(hab.num = factor(recode(Habitat, Cali=1, Delhi=2, Fiji=3)))

ggplot(data1, aes(NMDS1, NMDS2)) + 
  geom_point(aes(colour=Part, size=factor(Replicas), shape=Species, fill=hab.num)) + 
  geom_text(aes(x=NMDS1,y=NMDS2,label=hab.num)) +
  scale_fill_discrete(labels=paste(levels(data1$hab.num), "=", levels(data1$Habitat))) +
  guides(fill=guide_legend(keywidth=unit(0,"mm"), override.aes=list(size=0, colour=NA))) +
  labs(size="Replicas", fill="Habitat") +
  theme_classic()

enter image description here