简体   繁体   English

R中成对距离列表的距离矩阵

[英]Distance matrix to pairwise distance list in R

Is there any R package to obtain a pairwise distance list if my input file is a distance matrix For eg, if my input is a data.frame like this:如果我的输入文件是距离矩阵,是否有任何 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

I want the output as:我希望输出为:

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

I found a question to do the opposite function using package 'reshape' but could not tweak it to get what I wanted.我发现了一个问题,可以使用包“reshape”执行相反的功能,但无法对其进行调整以获得我想要的。

A couple of other options:其他几个选项:

  1. Generate some data生成一些数据

    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. Assuming you just want the distances for pairs defined by the upper triangle of the distance matrix, you can do:假设您只想要由距离矩阵的上三角形定义的对的距离,您可以执行以下操作:

     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. Alternatively, if you want distances for all pairs (in both directions):或者,如果您想要所有对的距离(在两个方向上):

     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

    or the following, which excludes any NA distances, but doesn't keep the column/row names (though this would be easy to rectify since we have the column/row indices):或以下,排除任何NA距离,但不保留列/行名称(尽管这很容易纠正,因为我们有列/行索引):

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

If you have a data.frame you could do something like:如果您有一个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

Another approach if you have it as a matrix with row+col-names is to use reshape2 directly:如果您将其作为具有行+列名称的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

I suppose you have a contingency table or a matrix defined as follow:我想你有一个列联表或矩阵定义如下:

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

Then you simply need a data.frame conversion, and remove NA/0's:然后你只需要一个 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

Here is an example using the spaa-package .这是使用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),]

Output:输出:

   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 Answer Tidymodels 答案

This is exactly the type of thing that the broom package excels at.这正是扫帚包擅长的类型。 It is a tidymodels package.这是一个tidymodels包。

Borrowing the dummy data from jbaums answer.借用 jbaums 答案中的虚拟数据。

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

This is a single function call.这是一个单一的函数调用。

library(broom)
tidy(D)

Which returns哪个返回

 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

Note, it also works for different values of diag and upper as well.请注意,它也适用于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