使用 ggplot 的素食主义者 ordiellipse 计算椭圆数据时的空数据框

Empty data frame when computing ellipse data with vegan's ordiellipse for ggplot

我正在尝试按照 this post 的有用建议,使用 ordiellipse 函数添加省略号,在 ggplot 中对 NMDS 的数据点进行分组。但是,虽然我没有收到任何错误消息或警告,但计算椭圆数据会生成一个空数据框。 数据集可用here,我的代码如下:

library(vegan)
library(ggplot2)

setwd("C:")
veg_matrix <- read.csv("161019_vegetation_matrix.csv",header=T); veg_matrix[2:123] <- lapply(veg_matrix[2:123],as.character); veg_matrix[2:123] <- lapply(veg_matrix[2:123],as.numeric)
rownames(veg_matrix) <- veg_matrix[,1]; veg_matrix <- veg_matrix[,-1] # remove non-numeric rownames (=plot codes) from dataset
speciescomp_NMDS = metaMDS(veg_matrix, k=2, trymax=100, distance="raup", na.rm=T)
plot(speciescomp_NMDS,display="sites",type="n")

# add grouping data
plot_scores <- as.data.frame(scores(speciescomp_NMDS))
plot_scores$plot <- rownames(plot_scores);plot_scores <- cbind(plot_scores,data.frame(matrix(unlist(strsplit(plot_scores$plot,"_")),nrow=24,byrow=T)))[,-3]; colnames(plot_scores)[c(3,4)] <- c("summit","aspect")
plot_scores$group <- ""
plot_scores$group[plot_scores$summit=="BUF"|plot_scores$summit=="SES"] <- "low"
plot_scores$group[plot_scores$summit=="CHA"|plot_scores$summit=="MIN"] <- "intermediate"
plot_scores$group[plot_scores$summit=="CUO"|plot_scores$summit=="GAJ"] <- "high"
plot_scores$group <- transform(plot_scores, as.factor(plot_scores$group))

# compute ellipse data
ord <- ordiellipse(speciescomp_NMDS,plot_scores$group,display = "sites", kind = "sd", conf = .95, label=T)

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

df_ell_level <- data.frame()
for(g in levels(plot_scores$group)){
  if(is.null(ord[[g]])) next
  df_ell_level <- rbind(df_ell_level,
                  cbind(as.data.frame(with(plot_scores[plot_scores$group==g,],
                                           f_ellipse(ord[[g]]$cov,ord[[g]]$center,ord[[g]]$scale)))
                        ,level=group))
}

任何关于如何处理这一问题的想法将不胜感激!

首先将group转换为因数

plot_scores <- transform(plot_scores, group = as.factor(group))

如果我们现在将您的循环修复为:

df_ell_level <- data.frame()
for(g in levels(plot_scores$group)){
  if(is.null(ord[[g]])) next
  df_ell_level <- 
    rbind(df_ell_level,
          cbind(as.data.frame(f_ellipse(ord[[g]]$cov, ord[[g]]$center, ord[[g]]$scale)),
                level=g)
         )
}

然后我得到一个包含 301 行的数据框。但是我已经从调用中删除了很多不必要的代码,您真的不想 rbind() 在这样的循环中将数据帧放在一起。