为什么树状图结构与我在 3D PCoA 中看到的数据不同?

Why is the dendrogram structure different from what I see of my data in a 3D PCoA?

提问人:vanguard605 提问时间:10/28/2023 最后编辑:kjetil b halvorsenvanguard605 更新时间:11/10/2023 访问量:22

问:

此问题是从 Stack Overflow 迁移而来的,因为它可以在交叉验证中回答。16 天前迁移

我对从一系列物种分布模型文本计算出的相异矩阵进行了分层聚类,我似乎在数据的树状图和 3D PCoA 之间获得了不同的可见结构。我尝试过其他聚类算法,但不能,结构总是与 PCoA 图不同。知道为什么吗?

我为树状图编写的代码在这里:

overlap = read.csv(file.choose(), row.names = 1, header = TRUE)
library(dendextend)
hc <- hclust(as.dist(overlap, diag = TRUE), method= "ward.D2")
par(mar=c(4, 10, 1, 1), cex=0.8)
plot_horiz.dendrogram(hc, side=TRUE)
#abline(v=0.55, col="grey", lty=2, lwd=3)
title(main="Warren's I", xlab="Dissimilarity")

最终结果是这样的:

dendrogram

3D PCoA 代码如下:

library(rgl)
pcoa = cmdscale(as.dist(overlap), k=3, eig=T, add = TRUE) 
         # run PCOA, add term is for negative eigenvalues
pcoa_scores = data.frame(pcoa$points) #save scores to data frame

colnames(pcoa_scores) = c("PCoA1","PCoA2", "PCoA3")

plot3d(x=pcoa_scores$PCoA1, y=pcoa_scores$PCoA2, z=pcoa_scores$PCoA3,
   xlab = "PCoA1", ylab = "PCoA2", zlab = "PCoA3",
   size = 3)
with(pcoa_scores, text3d(x=pcoa_scores$PCoA1, y=pcoa_scores$PCoA2, 
 z=pcoa_scores$PCoA3, 
     texts = str_trunc(row.names(pcoa_scores), 15)))

由于 3D 情节是可操作的,因此我不包含图像并鼓励其他人玩弄该情节。

R 分层聚类 树状图

评论


答:

0赞 Lukas Lohse 11/10/2023 #1

你用了很多我不熟悉的东西,但快速检查一下,就会发现你的 pcoa 中的特征值直到最后 3 或 4 个才下降,这意味着只看前 3 个主要成分是毫无用处的,因为它只覆盖了 11.4% 的数据“方差”。

pcoa <- cmdscale(as.dist(overlap), k = 3, eig = T, add = T)

plot(pcoa$eig)
sum(pcoa$eig[1:3])/sum(pcoa$eig)
pcoa$GOF # Goodness of fit, see here https://ichthyology.usm.edu/courses/multivariate/mar_3.pdf

enter image description here

1赞 Matt Dawdy 3/11/2009 #2

您仍然可以使用 Sitemap.sitemap 文件来控制导航,但您不会使用 asp.net 中的任何内置控件来实现此目的。我刚刚在我刚刚完成的网站上做了几乎这件事。

使所有页面都继承自基页类(或使用母版页,无论哪种方式,您都只有 1 个代码副本。

在每个页面上创建一个 div 或 span,命名为适当的名称(divNav 或 spnNav 或其他名称)。

在基础页面中,在页面加载时,遍历所有站点地图节点以查找当前页面的节点。这需要是一个递归调用。

    // Pass the current page url, all the way through the .aspx.  In other words, do NOT pass any kind of 
    // query string.
    private SiteMapNode GetCurrentNode(string _sCurrentPageURL, SiteMapNode _oNode)
    {
        SiteMapNode oNodeRet = null;

        foreach (SiteMapNode oNodeCheck in _oNode.ChildNodes)
        {
            if (oNodeCheck.HasChildNodes == true)
            {
                oNodeRet = GetCurrentNode(_sCurrentPageURL, oNodeCheck);
            }

            if (oNodeRet != null)
                break;

            string sUrl = oNodeCheck.Url.ToLower();
            int iPos = sUrl.IndexOf("?");
            if (iPos > 0)
                sUrl = sUrl.Substring(0, iPos);
            iPos = sUrl.LastIndexOf("/");
            if (iPos > 0)
                sUrl = sUrl.Substring(iPos);

            if (sUrl == _sCurrentPageURL)
            {
                oNodeRet = oNodeCheck;
                break;
            }
        }
        return oNodeRet;
    }

获得当前节点后,获取其父节点。

添加一个链接(您称之为“返回文件夹的向上菜单”)。

然后在父级中执行 foreach(SiteMapNode。子节点)

为每个子项添加一个链接。

因此,我们在每次页面加载时调用的主要调用是这样的:

    public string GetSecondaryNavItems()
    {
        string sRet = "";

        // Get the node that matches most of this url...
        System.Web.SiteMapNode oCurrNode = null;
        System.Web.SiteMapNode oCurrParentNode = null;

        string sCurrPage = GetURL(Request.ServerVariables["SCRIPT_NAME"].ToLower());

        oCurrNode = GetCurrentNode(sCurrPage, SiteMap.RootNode);

        if(oCurrNode != null)
            oCurrParentNode = oCurrNode.ParentNode;

        if(oCurrParentNode != null)
              if(oCurrParentNode != SiteMap.RootNode)
                  sRet += "Parent Folder link";

            if(oCurrNode != null)
            {
            foreach (System.Web.SiteMapNode oChild in oCurrParentNode.ChildNodes)
            {
                    sRet += "Link for child";
              }
        }
    }

我必须告诉你,上面的代码部分是我复制的,部分是我徒手制作的。但我认为,这应该给你一个良好的开端。

编辑:对不起!这是 GetURL 过程...

    public string GetURL(string _sURL)
    {
        string sRet = _sURL;

        int iPos = sRet.IndexOf("?");
        if (iPos > 0)
            sRet = sRet.Substring(0, iPos);
        iPos = sRet.LastIndexOf("/");
        if (iPos > 0)
            sRet = sRet.Substring(iPos);

        return sRet;
    }

评论

0赞 Kieran Senior 3/11/2009
如果你只是在你有时间的时候检查我的编辑,那就太好了。干杯
0赞 Matt Dawdy 3/12/2009
我刚刚为您添加了 C# 中的 GetURL,但您可能应该已经起作用,因为我敢打赌您没有在这些页面上使用查询字符串。我再看一眼。
0赞 Kieran Senior 3/12/2009
我似乎找不到它的问题,但没有任何输出,尽管这可能与我的站点地图有关(我已经把它放在我的帖子的编辑中)。不幸的是,我明天再次上班时必须检查。为片段欢呼,这是完全有道理的。
0赞 Matt Dawdy 3/16/2009
嘿 Kezzer -- 我明天会看一下这个,但我怀疑问题可能在于你有几个 URL 位于 Accounts 文件夹下。我不确定我的代码是否考虑到了这一点。我明天会使用你的站点地图,看看我能找到什么。
0赞 Kieran Senior 3/16/2009
从字面上看,这是一个测试站点地图,如果站点地图在逻辑上有问题,请给我大喊大叫。我们的站点地图非常大,最大深度可能为 5 或 6。干杯
1赞 Kieran Senior 3/16/2009 #3

虽然我不应该回应,但我实际上会问一些进一步的问题。是否有可能做完全相同的事情,但使用由简单和元素组成的页面?我之所以这么问,是因为我们的“站点地图”实际上在安全性和功能方面都更先进一些。我们运行的菜单实际上具有带有输入框的动态下拉列表,这是站点地图中无法复制的。<ul><li>

所以,这个想法是做完全相同的事情,除了

<ul>
   <li>
      <ul>
         <li></li>
      </ul>
   </li>
   <li></li>
   <li></li>
</ul>

结构。根节点上必须有一个 runat=“server”,这样你就可以遍历所有子元素?这样我就可以在我的 和 元素中放置任何内容。<li></li>

我们的安全性也相当零星,站点地图也没有我们正在寻找的那种精细控制。