Ich möchte ein hclust-Dendrogramm von R in eine Datentabelle exportieren, um es anschließend in eine andere ("hausgemachte") Software zu importieren. str(unclass(fit))
bietet eine Textübersicht für das Dendrogramm, aber was ich suche, ist in Wirklichkeit eine numerische Tabelle. Ich habe mir das Bioconductor ctc-Paket angeschaut, aber die Ausgabe, die es produziert, sieht etwas kryptisch aus. Ich möchte etwas ähnliches zu dieser Tabelle haben: http://stn.spotfire.com/spotfire_client_help/heat/heat_importing_exporting_dendrograms.htm Gibt es eine Möglichkeit, dies aus einem hclust-Objekt in R zu bekommen?Exportieren eines Dendrogramms als Tabelle in R
5
A
Antwort
1
Es gibt Paket, das genau Gegenteil tut, was Sie wollen - Labeltodendro ;-)
Aber im Ernst, kannst du nicht einfach manuell die Elemente aus hclust
-Objekt extrahieren (zB $merge
, $height
, $order
) und benutzerdefinierten erstellen Tabelle aus den extrahierten Elementen?
3
Falls jemand auch Interesse am Dendrogramm-Export hat, hier ist meine Lösung. Wahrscheinlich ist es nicht der beste, als ich erst vor kurzem mit R angefangen habe, aber zumindest funktioniert es. Vorschläge zur Verbesserung des Codes sind daher willkommen.
Also, wenn hr
mein hclust Objekt ist und df
ist meine Daten, die erste Spalte, die einen einfachen Index ausgehend von 0 enthält, und die Zeilennamen sind die Namen der gruppierten Elemente:
# Retrieve the leaf order (row name and its position within the leaves)
leaf.order <- matrix(data=NA, ncol=2, nrow=nrow(df),
dimnames=list(c(), c("row.num", "row.name")))
leaf.order[,2] <- hr$labels[hr$order]
for (i in 1:nrow(leaf.order)) {
leaf.order[which(leaf.order[,2] %in% rownames(df[i,])),1] <- df[i,1]
}
leaf.order <- as.data.frame(leaf.order)
hr.merge <- hr$merge
n <- max(df[,1])
# Re-index all clustered leaves and nodes. First, all leaves are indexed starting from 0.
# Next, all nodes are indexed starting from max. index leave + 1.
for (i in 1:length(hr.merge)) {
if (hr.merge[i]<0) {hr.merge[i] <- abs(hr.merge[i])-1}
else { hr.merge[i] <- (hr.merge[i]+n) }
}
node.id <- c(0:length(hr.merge))
# Generate dendrogram matrix with node index in the first column.
dend <- matrix(data=NA, nrow=length(node.id), ncol=6,
dimnames=list(c(0:(length(node.id)-1)),
c("node.id", "parent.id", "pruning.level",
"height", "leaf.order", "row.name")))
dend[,1] <- c(0:((2*nrow(df))-2)) # Insert a leaf/node index
# Calculate parent ID for each leaf/node:
# 1) For each leaf/node index, find the corresponding row number within the merge-table.
# 2) Add the maximum leaf index to the row number as indexing the nodes starts after indexing all the leaves.
for (i in 1:(nrow(dend)-1)) {
dend[i,2] <- row(hr.merge)[which(hr.merge %in% dend[i,1])]+n
}
# Generate table with indexing of all leaves (1st column) and inserting the corresponding row names into the 3rd column.
hr.order <- matrix(data=NA,
nrow=length(hr$labels), ncol=3,
dimnames=list(c(), c("order.number", "leaf.id", "row.name")))
hr.order[,1] <- c(0:(nrow(hr.order)-1))
hr.order[,3] <- t(hr$labels[hr$order])
hr.order <- data.frame(hr.order)
hr.order[,1] <- as.numeric(hr.order[,1])
# Assign the row name to each leaf.
dend <- as.data.frame(dend)
for (i in 1:nrow(df)) {
dend[which(dend[,1] %in% df[i,1]),6] <- rownames(df[i,])
}
# Assign the position on the dendrogram (from left to right) to each leaf.
for (i in 1:nrow(hr.order)) {
dend[which(dend[,6] %in% hr.order[i,3]),5] <- hr.order[i,1]-1
}
# Insert height for each node.
dend[c((n+2):nrow(dend)),4] <- hr$height
# All leaves get the highest possible pruning level
dend[which(dend[,1] <= n),3] <- nrow(hr.merge)
# The nodes get a decreasing index starting from the pruning level of the
# leaves minus 1 and up to 0
for (i in (n+2):nrow(dend)) {
if ((dend[i,4] != dend[(i-1),4]) || is.na(dend[(i-1),4])){
dend[i,3] <- dend[(i-1),3]-1}
else { dend[i,3] <- dend[(i-1),3] }
}
dend[,3] <- dend[,3]-min(dend[,3])
dend <- dend[order(-node.id),]
# Write results table.
write.table(dend, file="path", sep=";", row.names=F)
I habe gerade diesen Code benutzt und es hat perfekt funktioniert. Die große Schwierigkeit für mich? Das Lesen der Anweisungen darüber, welche Eingabedaten erforderlich waren - diese Beschreibung des Datenrahmens "df" ist tatsächlich wichtig, Leute. – eleanorahowe
@Eleanor Ich bin froh, dass Sie es nützlich fanden. Sie haben Recht, der Code beruht auf einer bestimmten Struktur des Eingabedatenrahmens. Ich hoffe, du hast nicht zu viel Zeit damit verbracht, es herauszufinden. – AnjaM