我正在努力完成我在素食主义者和ggplot2中创建的NMDS图,但无法弄清楚如何在图中添加envfit物种加载矢量。当我尝试它时说“无效的图形状态”。
以下示例稍微修改了另一个问题(Plotting ordiellipse function from vegan package onto NMDS plot created in ggplot2),但它完全表达了我想要包含的示例,因为我首先使用此问题来帮助我将metaMDS导入ggplot2:
library(vegan)
library(ggplot2)
data(dune)
# calculate distance for NMDS
NMDS.log<-log(dune+1)
sol <- metaMDS(NMDS.log)
# Create meta data for grouping
MyMeta = data.frame(
sites = c(2,13,4,16,6,1,8,5,17,15,10,11,9,18,3,20,14,19,12,7),
amt = c("hi", "hi", "hi", "md", "lo", "hi", "hi", "lo", "md", "md", "lo",
"lo", "hi", "lo", "hi", "md", "md", "lo", "hi", "lo"),
row.names = "sites")
# plot NMDS using basic plot function and color points by "amt" from MyMeta
plot(sol$points, col = MyMeta$amt)
# same in ggplot2
NMDS = data.frame(MDS1 = sol$points[,1], MDS2 = sol$points[,2])
ggplot(data = NMDS, aes(MDS1, MDS2)) +
geom_point(aes(data = MyMeta, color = MyMeta$amt))
#Add species loadings
vec.sp<-envfit(sol$points, NMDS.log, perm=1000)
plot(vec.sp, p.max=0.1, col="blue")
答案 0 :(得分:7)
(另外优秀的)接受的答案的问题,并解释了为什么向量在所包含的图中具有相同的长度[注意,现在已经编辑了接受的答案以按照方式缩放箭头我在下面描述,为了避免混淆Q&amp; A ]的用户,$vectors$arrows
返回的对象的envfit()
组件中存储的是方向余弦拟合向量。这些都是单位长度,因此@Didzis Elferts的图中的箭头都是相同的长度。这与plot(envfit(sol, NMDS.log))
的输出不同,因为我们通过与排序配置(“轴”)的相关性来缩放矢量箭头坐标。这样,与排序配置显示弱关系的物种会得到较短的箭头。缩放是通过将方向余弦乘以sqrt(r2)
来完成的,其中r2
是打印输出表中显示的值。当将向量添加到现有图中时,素食也会尝试缩放矢量集,以便它们填充可用的绘图空间,同时保持箭头的相对长度。如何完成此操作将在?envfit
的详细信息部分中讨论,并且需要使用未导出的函数vegan:::ordiArrowMul(result_of_envfit)
。
以下是一个完整的工作示例,使用 ggplot2 复制plot.envfit
的行为:
library(vegan)
library(ggplot2)
library(grid)
data(dune)
# calculate distance for NMDS
NMDS.log<-log1p(dune)
set.seed(42)
sol <- metaMDS(NMDS.log)
scrs <- as.data.frame(scores(sol, display = "sites"))
scrs <- cbind(scrs, Group = c("hi","hi","hi","md","lo","hi","hi","lo","md","md",
"lo","lo","hi","lo","hi","md","md","lo","hi","lo"))
set.seed(123)
vf <- envfit(sol, NMDS.log, perm = 999)
如果我们此时停下来并查看vf
:
> vf
***VECTORS
NMDS1 NMDS2 r2 Pr(>r)
Belper -0.78061195 -0.62501598 0.1942 0.174
Empnig -0.01315693 0.99991344 0.2501 0.054 .
Junbuf 0.22941001 -0.97332987 0.1397 0.293
Junart 0.99999981 -0.00062172 0.3647 0.022 *
Airpra -0.20995196 0.97771170 0.5376 0.002 **
Elepal 0.98959723 0.14386566 0.6634 0.001 ***
Rumace -0.87985767 -0.47523728 0.0948 0.429
.... <truncated>
因此r2
数据用于缩放NMDS1
和NMDS2
列中的值。最终的情节是:
spp.scrs <- as.data.frame(scores(vf, display = "vectors"))
spp.scrs <- cbind(spp.scrs, Species = rownames(spp.scrs))
p <- ggplot(scrs) +
geom_point(mapping = aes(x = NMDS1, y = NMDS2, colour = Group)) +
coord_fixed() + ## need aspect ratio of 1!
geom_segment(data = spp.scrs,
aes(x = 0, xend = NMDS1, y = 0, yend = NMDS2),
arrow = arrow(length = unit(0.25, "cm")), colour = "grey") +
geom_text(data = spp.scrs, aes(x = NMDS1, y = NMDS2, label = Species),
size = 3)
这会产生:
答案 1 :(得分:4)
首先添加库。另外,库grid
是必需的。
library(ggplot2)
library(vegan)
library(grid)
data(dune)
进行metaMDS分析并将结果保存在数据框中。
NMDS.log<-log(dune+1)
sol <- metaMDS(NMDS.log)
NMDS = data.frame(MDS1 = sol$points[,1], MDS2 = sol$points[,2])
添加物种载荷并将其保存为数据框。箭头余弦的方向存储在列表vectors
和矩阵arrows
中。要获取箭头的坐标,应将这些方向值乘以r2
中存储的vectors$r
值的平方根。更直接的方法是使用@Gavin Simpson回答中提供的函数scores()
。然后添加包含species
名称的新列。
vec.sp<-envfit(sol$points, NMDS.log, perm=1000)
vec.sp.df<-as.data.frame(vec.sp$vectors$arrows*sqrt(vec.sp$vectors$r))
vec.sp.df$species<-rownames(vec.sp.df)
箭头添加geom_segment()
,物种名称加geom_text()
。对于这两个任务,使用数据框vec.sp.df
。
ggplot(data = NMDS, aes(MDS1, MDS2)) +
geom_point(aes(data = MyMeta, color = MyMeta$amt))+
geom_segment(data=vec.sp.df,aes(x=0,xend=MDS1,y=0,yend=MDS2),
arrow = arrow(length = unit(0.5, "cm")),colour="grey",inherit_aes=FALSE) +
geom_text(data=vec.sp.df,aes(x=MDS1,y=MDS2,label=species),size=5)+
coord_fixed()
答案 2 :(得分:2)
我可以迟到一些事吗?
Envfit提供pvalues,有时你只想绘制重要参数(素食主义者可以为你做的事情,在plot命令中p = 0.05)。我努力用ggplot2做到这一点。这是我的解决方案,也许你找到一个更优雅的解决方案?
从Didzis的回答开始:
ef<-envfit(sol$points, NMDS.log, perm=1000)
ef.df<-as.data.frame(ef$vectors$arrows*sqrt(ef$vectors$r))
ef.df$species<-rownames(ef.df)
#only significant pvalues
#shortcutting ef$vectors
A <- as.list(ef$vectors)
#creating the dataframe
pvals<-as.data.frame(A$pvals)
arrows<-as.data.frame(A$arrows*sqrt(A$r))
C<-cbind(arrows, pvals)
#subset
Cred<-subset(C,pvals<0.05)
Cred <- cbind(Cred, Species = rownames(Cred))
“Cred”现在可以在geom_segment-argument中实现,如上所述。
答案 3 :(得分:0)
简短的补充:要获得plot.envfit
中ggplot2
功能的完整表示,又称为“箭头长度充分利用绘图区域”,需要应用一个因素。我不知道上面的答案是否有意将其遗漏,如Gavin特别提到的那样?只需使用arrow_factor <- ordiArrowMul(vf)
提取所需的比例因子,然后可以将其应用于spp.scrs
中的两个NMDS列,或者可以像
arrow_factor <- ordiArrowMul(vf)
spp.scrs <- as.data.frame(scores(vf, display = "vectors")) * arrow_factor
spp.scrs <- cbind(spp.scrs, Species = rownames(spp.scrs), Pvalues = vf$vectors$pvals, R_squared = vf$vectors$r)
# select significance similarly to `plot(vf, p.max = 0.01)`
spp.scrs <- subset(spp.scrs, Pvalues < 0.01)
# you can also add the arrow factor in here (don't do both!)
ggplot(scrs) +
geom_point(mapping = aes(x = NMDS1, y = NMDS2, colour = Group)) +
coord_fixed() + ## need aspect ratio of 1!
geom_segment(data = spp.scrs,
aes(x = 0, xend = NMDS1 * arrow_factor, y = 0, yend = NMDS2 * arrow_factor),
arrow = arrow(length = unit(0.25, "cm")), colour = "grey") +
geom_text(data = spp.scrs, aes(x = NMDS1 * arrow_factor, y = NMDS2 * arrow_factor, label = Species),
size = 3)