0

I am trying to fill shapes with colors gradient corresponding to a continuous variable. I don't have any errors, but it does not print on the graph.

I tried to use as.numeric to make sure the variable is continuous.

The NMDS is already calculated and it works. Everything works except the color gradient.

ggplot()+ 
        geom_point(data = NMDS.all.taxa, aes(y = NMDS2, x = NMDS1, fill = env$elev.num), shape = env$saison, size = 4)+ #this is the points
        geom_path(data = df_ell.all.taxa, aes(x = NMDS1, y = NMDS2, colour = group))+     ##Elipses
        scale_fill_gradient2(low = "green", mid = "blue", high = "red", midpoint = 1800)+   ##fill
        theme_bw()+
        theme(panel.background = element_blank(), 
              panel.grid.major = element_blank(),  #remove major-grid labels
              panel.grid.minor = element_blank(),  #remove minor-grid labels
              plot.background = element_blank() 
        ) 

It gives me a NMDS with everything except that the shapes are empty. Not any Error codes.

To recreate aspects of the data:

library(vegan)
Macro_AUG_2019_rep.<- matrix(0:10, ncol = 20, nrow = 50) 
env <- data.frame(Traitement = sample(c("n","r"),50, replace = TRUE), 
                  saison = sample(c("S","A"),50, replace = TRUE),
                  Elevation = sample(1000:1049), 
                  Site = sample(c("lake1","lake2","lake3","lake4","lake5","lake6","lake7"), 
                                50, replace = TRUE))

spe.nmds <- metaMDS(Macro_AUG_2019_rep., distance='bray', k=2, try=999, maxit=500)
NMDS.all.taxa <- data.frame(NMDS1 = spe.nmds$points[,1],
                            NMDS2 = spe.nmds$points[,2], 
                            group = env$Traitement,
                            sites = env$Site)

veganCovEllipse <- function(cov, center = c(0, 0), scale = 1.75, npoints = 100) { 
  theta <- (0:npoints) * 2 * pi/npoints 
  Circle <- cbind(cos(theta), sin(theta)) 
  t(center + scale * t(Circle %*% chol(cov))) 
}

df_ell.all.taxa <- data.frame()
for(g in levels(NMDS.all.taxa$group)){ 
  df_ell.all.taxa <- rbind(
    df_ell.all.taxa, 
    cbind(as.data.frame(with(NMDS.all.taxa[NMDS.all.taxa$group == g, ], 
                             veganCovEllipse(cov.wt(cbind(NMDS1, NMDS2),
                                                    wt=rep(1 / length(NMDS1), 
                                                           length(NMDS1)))$cov,
                                             center=c(mean(NMDS1), mean(NMDS2))))),
          group = g)
  ) 
}
NMDS.mean.all.taxa = aggregate(NMDS.all.taxa[ ,c("NMDS1", "NMDS2")], 
                               list(group = NMDS.all.taxa$group), 
                               mean)
Community
  • 1
  • 1

1 Answers1

1

ggplot2 doesn't play nice with $ operators in aes() functions, so it would be good practise to avoid these by appending the env$Elevation and env$saison to your main data.frame:

df <- cbind(NMDS.all.taxa, Elevation = env$Elevation, Saison = env$saison)

Now, if I understood correctly, the problem was that the geom_point shapes aren't filled. The shape aesthetic in ggplot2 is (I think) identical to the pch argument in base R plots, so we can see what the values would mean:

enter image description here

Factor variables are integers dressed up with a level-label, so the env$saison that you were using would pass down 1s and 2s as shapes. These shapes are line-only, without any fill associated with them.

Thus, to fix the problem we need to let ggplot know what shapes we actually want, 21 and 24 for example. To map your factor variable to these shapes, we'll define the shapes inside the aes() function. Then, we can use scale_shape_manual() to set the correct shapes.

# I defined the xy mapping in the main `ggplot()` call so that we
# don't need to do this seperately for the path and points
ggplot(data = df, aes(NMDS1, NMDS2))+ 
  geom_point(aes(fill = Elevation, shape = Saison), 
             size = 4) +
  geom_path(data = df_ell.all.taxa, 
            aes(colour = group)) +
  scale_shape_manual(values = c(21, 24)) +
  scale_fill_gradient2(low = "green", mid = "blue", high = "red",
                       # I adjusted the midpoint to match example
                       midpoint = mean(df$Elevation))

Which gave me the following plot:

enter image description here

As an aside, your problem would have been easily illustrated with a build-in dataset. It is more in line with what a minimal reproducible example is, and it would have saved your time copying your data analysis code. Example below:

ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
  geom_point(aes(fill = Petal.Width), shape = iris$Species) +
  scale_fill_gradient()

To which the answer would have been:

ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
  geom_point(aes(fill = Petal.Width, shape = Species)) +
  scale_fill_gradient() +
  scale_shape_manual(values = c(21, 22, 24))
teunbrand
  • 26,691
  • 4
  • 25
  • 49