【问题标题】:Is there a better way to hierarchically cluster in R?有没有更好的方法在 R 中分层聚类?
【发布时间】:2011-12-01 03:35:08
【问题描述】:

我想先按行再按列进行层次聚类。我想出了一个完整的解决方案:

#! /path/to/my/Rscript --vanilla
args <- commandArgs(TRUE)
mtxf.in <- args[1]
clusterMethod <- args[2]
mtxf.out <- args[3]

mtx <- read.table(mtxf.in, as.is=T, header=T, stringsAsFactors=T)

mtx.hc <- hclust(dist(mtx), method=clusterMethod)
mtx.clustered <- as.data.frame(mtx[mtx.hc$order,])
mtx.c.colnames <- colnames(mtx.clustered)
rownames(mtx.clustered) <- mtx.clustered$topLeftColumnHeaderName
mtx.clustered$topLeftColumnHeaderName <- NULL
mtx.c.t <- as.data.frame(t(mtx.clustered), row.names=names(mtx))
mtx.c.t.hc <- hclust(dist(mtx.c.t), method=clusterMethod)
mtx.c.t.c <- as.data.frame(mtx.c.t[mtx.c.t.hc$order,])
mtx.c.t.c.t <- as.data.frame(t(mtx.c.t.c))
mtx.c.t.c.t.colnames <- as.vector(names(mtx.c.t.c.t))
names(mtx.c.t.c.t) <- mtx.c.colnames[as.numeric(mtx.c.t.c.t.colnames) + 1]

write.table(mtx.c.t.c.t, file=mtxf.out, sep='\t', quote=F, row.names=T)

变量mtxf.inmtxf.out 分别代表输入矩阵和聚类输出矩阵文件。变量clusterMethodhclust方法之一,如singleaverage等。

作为示例输入,这里是一个数据矩阵:

topLeftColumnHeaderName col1    col2    col3    col4    col5    col6
row1    0       3       0       0       0       3
row2    6       6       6       6       6       6
row3    0       3       0       0       0       3
row4    6       6       6       6       6       6
row5    0       3       0       0       0       3
row6    0       3       0       0       0       3

运行此脚本,我丢失了来自mtxf.in 的左上角元素。以下是此脚本的输出:

col5    col4    col1    col3    col2    col6
row6    0       0       0       0       3       3
row5    0       0       0       0       3       3
row1    0       0       0       0       3       3
row3    0       0       0       0       3       3
row2    6       6       6       6       6       6
row4    6       6       6       6       6       6

我的问题:除了寻找一种方法来保留输入矩阵文件的原始结构外,我也不知道这会消耗多少内存,也不知道是否有更快、更干净、更像“R”的方式这样做。

真的很难在 R 中按行和列进行聚类吗?有建设性的方法来改进这个脚本吗?谢谢你的建议。

【问题讨论】:

  • 实际上现在有一个专门用于代码审查的网站,可能也值得一试。 codereview.stackexchange.com
  • 我实际上想说你更有可能在这里获得 R 特定的帮助。

标签: r cluster-analysis hierarchical rscript


【解决方案1】:

一旦您清理了数据(即删除了第一列),这实际上只需要三行代码:

清理数据(从第一列分配行名,然后删除第一列):

dat <- mtfx.in
rownames(dat) <- dat[, 1]
dat <- dat[, -1]

聚类和重新排序:

row.order <- hclust(dist(dat))$order
col.order <- hclust(dist(t(dat)))$order

dat[row.order, col.order]

结果:

     col5 col4 col1 col3 col2 col6
row6    0    0    0    0    3    3
row5    0    0    0    0    3    3
row1    0    0    0    0    3    3
row3    0    0    0    0    3    3
row2    6    6    6    6    6    6
row4    6    6    6    6    6    6

【讨论】:

    【解决方案2】:

    老实说,我并不完全清楚你为什么要做一些你正在做的事情,所以我完全有可能误解了你要找的东西。如果我偏离了基地,请告诉我,我会删除这个答案。

    但我怀疑,如果您使用row.names = 1 读取数据以指示第一列实际上是行名,那么您的生活会容易得多(并且您的结果实际上是正确的)。例如:

    #Read the data in
    d1 <- read.table(textConnection("topLeftColumnHeaderName col1    col2    col3    col4    col5    col6
     row1    0       3       0       0       0       3
     row2    6       6       6       6       6       6
     row3    0       3       0       0       0       3
     row4    6       6       6       6       6       6
     row5    0       3       0       0       0       3
     row6    0       3       0       0       0       3"),
       sep = "",as.is = TRUE,header = TRUE,
       stringsAsFactors = TRUE,row.names = 1)
    
    #So d1 looks like this: 
    d1
         col1 col2 col3 col4 col5 col6
    row1    0    3    0    0    0    3
    row2    6    6    6    6    6    6
    row3    0    3    0    0    0    3
    row4    6    6    6    6    6    6
    row5    0    3    0    0    0    3
    row6    0    3    0    0    0    3
    
    #Simple clustering based on rows 
    clus1 <- hclust(dist(d1))
    d2 <- d1[clus1$order,]
    d2
         col1 col2 col3 col4 col5 col6
    row6    0    3    0    0    0    3
    row5    0    3    0    0    0    3
    row1    0    3    0    0    0    3
    row3    0    3    0    0    0    3
    row2    6    6    6    6    6    6
    row4    6    6    6    6    6    6
    
    #Now cluster on columns and display the result 
    clus2 <- hclust(dist(t(d2)))
    t(t(d2)[clus2$order,])
         col5 col4 col1 col3 col2 col6
    row6    0    0    0    0    3    3
    row5    0    0    0    0    3    3
    row1    0    0    0    0    3    3
    row3    0    0    0    0    3    3
    row2    6    6    6    6    6    6
    row4    6    6    6    6    6    6
    

    既然你标记了这个code-review,我想我还要指出,在风格上,许多R 人不喜欢使用TF 作为布尔值,因为它们可以被屏蔽,而TRUE 和@987654327 @ 不能。

    【讨论】:

    • 我对你的回答感到困惑。您是说我的代码进行的聚类是错误的吗?你似乎得到了和我一样的最终结果。最终,我的目标是保留输入中的数据(例如左上角的标签)。
    • @AlexReynolds 对不起;我的意思是您当前的代码实际上包括第一轮聚类中的行名列。这意味着dist 将这个因素强制转换为 NA。它适用于您的示例,但我一般不会依赖它。请注意,Andrie 和我的一样,涉及使该列成为行名。不过,他的方法明确地保存了你想要的信息,所以我会跟随他的领导。
    猜你喜欢
    • 2011-04-29
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    相关资源
    最近更新 更多