簡體   English   中英

R中成對距離列表的距離矩陣

[英]Distance matrix to pairwise distance list in R

如果我的輸入文件是距離矩陣,是否有任何 R 包來獲取成對距離列表例如,如果我的輸入是這樣的 data.frame:

        A1      B1      C1      D1
 A1     0      0.85    0.45    0.96 
 B1            0       0.85    0.56
 C1                    0       0.45
 D1                            0

我希望輸出為:

A1  B1  0.85
A1  C1  0.45
A1  D1  0.96
B1  C1  0.85
B1  D1  0.56
C1  D1  0.45

我發現了一個問題,可以使用包“reshape”執行相反的功能,但無法對其進行調整以獲得我想要的。

其他幾個選項:

  1. 生成一些數據

    D <- dist(cbind(runif(4), runif(4)), diag=TRUE, upper=TRUE) # generate dummy data m <- as.matrix(D) # coerce dist object to a matrix dimnames(m) <- dimnames(m) <- list(LETTERS[1:4], LETTERS[1:4])
  2. 假設您只想要由距離矩陣的上三角形定義的對的距離,您可以執行以下操作:

     xy <- t(combn(colnames(m), 2)) data.frame(xy, dist=m[xy]) # X1 X2 dist # 1 AB 0.3157942 # 2 AC 0.5022090 # 3 AD 0.3139995 # 4 BC 0.1865181 # 5 BD 0.6297772 # 6 CD 0.8162084
  3. 或者,如果您想要所有對的距離(在兩個方向上):

     data.frame(col=colnames(m)[col(m)], row=rownames(m)[row(m)], dist=c(m)) # col row dist # 1 AA 0.0000000 # 2 AB 0.3157942 # 3 AC 0.5022090 # 4 AD 0.3139995 # 5 BA 0.3157942 # 6 BB 0.0000000 # 7 BC 0.1865181 # 8 BD 0.6297772 # 9 CA 0.5022090 # 10 CB 0.1865181 # 11 CC 0.0000000 # 12 CD 0.8162084 # 13 DA 0.3139995 # 14 DB 0.6297772 # 15 DC 0.8162084 # 16 DD 0.0000000

    或以下,排除任何NA距離,但不保留列/行名稱(盡管這很容易糾正,因為我們有列/行索引):

     data.frame(which(!is.na(m), arr.ind=TRUE, useNames=FALSE), dist=c(m))

如果您有一個data.frame ,您可以執行以下操作:

df <- structure(list(A1 = c(0, 0, 0, 0), B1 = c(0.85, 0, 0, 0), C1 = c(0.45, 
0.85, 0, 0), D1 = c(0.96, 0.56, 0.45, 0)), .Names = c("A1", "B1", 
"C1", "D1"), row.names = c(NA, -4L), class = "data.frame")

data.frame( t(combn(names(df),2)), dist=t(df)[lower.tri(df)] )
  X1 X2 dist
1 A1 B1 0.85
2 A1 C1 0.45
3 A1 D1 0.96
4 B1 C1 0.85
5 B1 D1 0.56
6 C1 D1 0.45

如果您將其作為具有行+列名稱的matrix ,另一種方法是直接使用reshape2

mat <- structure(c(0, 0, 0, 0, 0.85, 0, 0, 0, 0.45, 0.85, 0, 0, 0.96, 
0.56, 0.45, 0), .Dim = c(4L, 4L), .Dimnames = list(c("A1", "B1", 
"C1", "D1"), c("A1", "B1", "C1", "D1")))

library(reshape2)
subset(melt(mat), value!=0)

   Var1 Var2 value
5    A1   B1  0.85
9    A1   C1  0.45
10   B1   C1  0.85
13   A1   D1  0.96
14   B1   D1  0.56
15   C1   D1  0.45

我想你有一個列聯表或矩陣定義如下:

mat = matrix(c(0, 0.85, 0.45, 0.96, NA, 0, 0.85, 0.56, NA, NA, 0, 0.45, NA,NA,NA,0), ncol=4)
cont = as.table(t(mat))

#     A    B    C    D
#A 0.00 0.85 0.45 0.96
#B      0.00 0.85 0.56
#C           0.00 0.45
#D                0.00

然后你只需要一個 data.frame 轉換,並刪除 NA/0 的:

df = as.data.frame(cont)
df = df[complete.cases(df),]
df[df[,3]!=0,]

#   Var1 Var2 Freq
#5     A    B 0.85
#9     A    C 0.45
#10    B    C 0.85
#13    A    D 0.96
#14    B    D 0.56
#15    C    D 0.45

這是使用spaa-package的示例。

exampleInput <- structure(list(A1 = c(0, 0, 0, 0), B1 = c(0.85, 0, 0, 0), 
C1 = c(0.45, 0.85, 0, 0), D1 = c(0.96, 0.56, 0.45, 0)), 
.Names = c("A1", "B1", "C1", "D1"), row.names = c(NA, -4L), class = "data.frame")

library(spaa)
pairlist <- dist2list(as.dist(t(exampleInput)))
pairlist[as.numeric(pairlist$col) > as.numeric(pairlist$row),]

輸出:

   col row value
2   B1  A1  0.85
3   C1  A1  0.45
4   D1  A1  0.96
7   C1  B1  0.85
8   D1  B1  0.56
12  D1  C1  0.45

Tidymodels 答案

這正是掃帚包擅長的類型。 這是一個tidymodels包。

借用 jbaums 答案中的虛擬數據。

D <- dist(cbind(runif(4), runif(4))) # generate dummy data

這是一個單一的函數調用。

library(broom)
tidy(D)

哪個返回

 A tibble: 6 x 3
  item1 item2 distance
  <fct> <fct>    <dbl>
1 1     2        0.702
2 1     3        0.270
3 1     4        0.292
4 2     3        0.960
5 2     4        0.660
6 3     4        0.510

請注意,它也適用於diagupper的不同值。

tidy(dist(cbind(runif(4), runif(4)), diag=TRUE, upper=TRUE))
tidy(dist(cbind(runif(4), runif(4)), diag=FALSE, upper=TRUE))
tidy(dist(cbind(runif(4), runif(4)), diag=TRUE, upper=FALSE))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM