使用 R 中的 apply 将矩阵转换为配对列表?
Turn matrix into a paired list using apply in R?
我有一个类似于下面的矩阵,但更大。
vec <- c(0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0)
M <- matrix(vec, nrow = 4, byrow = TRUE)
colnames(M) <- rownames(M) <- LETTERS[1:4]
A, B, C, D
A, 0, 1, 1, 0
B, 0, 0, 1, 1
C, 1, 0, 0, 0
D, 0, 1, 1, 0
最终,我想要一个矩阵或 data.frame,其中每次行中的调用都有一个值时,我最终得到一个行名、列名对。因此,鉴于上述矩阵,我最终得到以下矩阵或数据框:
A,B
A,C
B,C
B,D
C,A
D,B
D,C
我可以用循环和 expand.grid 来做到这一点,但这似乎是我应该能够用应用函数来做的事情。例如,我可以像这样到达那里:
tmp <- apply(M, 1, function(x) colnames(M)[which(x > 0)])
这给了我
$A
[1] "B" "C"
$B
[1] "C" "D"
$C
[1] "A"
$D
[1] "B" "C"
如果这很容易,那么我可以将单元格中的数字(对于大于 0 的单元格)作为第三列吗?
采纳@Frank 关于 melt
的建议,这是使用它的一种方法 dplyr
:
library(reshape2)
library(dplyr)
M2 <- M %>%
melt(.) %>%
transmute(pair = paste(Var1, Var2, sep = ","),
value = value) %>%
filter(value > 0)
结果的顺序与您显示的不同,但我不清楚这对您是否重要。
library(tidyr)
M = as.data.frame(M)
M["rowid"] = row.names(M)
gather(M, colid, value, -rowid)
您不一定需要使用 apply()
循环。这是 base R 中的一个想法,它使用 which()
找到相关索引,然后进行一些简单的提取和组合。
wM <- which(M > 0, arr.ind = TRUE)
matrix(sort(paste(rownames(wM), colnames(M)[wM[,2]], sep = ",")))
# [,1]
# [1,] "A,B"
# [2,] "A,C"
# [3,] "B,C"
# [4,] "B,D"
# [5,] "C,A"
# [6,] "D,B"
# [7,] "D,C"
或者,您可以使用 row
和 col
代替 which
。
M0 <- M > 0
paste(rownames(M)[row(M)[M0]], colnames(M)[col(M)[M0]], sep = ",")
# [1] "C,A" "A,B" "D,B" "A,C" "B,C" "D,C" "B,D"
一种igraph
方法
library(igraph)
as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
graph_from_adjacency_matrix()
将矩阵作为输入,return 是一个图。使用weighted=TRUE
到return非零值作为权重。
as_data_frame
returns 具有关联属性的边列表(在本例中为权重)
所以对于你的例子,
as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
# from to weight
# 1 A B 1
# 2 A C 1
# 3 B C 1
# 4 B D 1
# 5 C A 1
# 6 D B 1
# 7 D C 1
我有一个类似于下面的矩阵,但更大。
vec <- c(0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0)
M <- matrix(vec, nrow = 4, byrow = TRUE)
colnames(M) <- rownames(M) <- LETTERS[1:4]
A, B, C, D
A, 0, 1, 1, 0
B, 0, 0, 1, 1
C, 1, 0, 0, 0
D, 0, 1, 1, 0
最终,我想要一个矩阵或 data.frame,其中每次行中的调用都有一个值时,我最终得到一个行名、列名对。因此,鉴于上述矩阵,我最终得到以下矩阵或数据框:
A,B
A,C
B,C
B,D
C,A
D,B
D,C
我可以用循环和 expand.grid 来做到这一点,但这似乎是我应该能够用应用函数来做的事情。例如,我可以像这样到达那里:
tmp <- apply(M, 1, function(x) colnames(M)[which(x > 0)])
这给了我
$A
[1] "B" "C"
$B
[1] "C" "D"
$C
[1] "A"
$D
[1] "B" "C"
如果这很容易,那么我可以将单元格中的数字(对于大于 0 的单元格)作为第三列吗?
采纳@Frank 关于 melt
的建议,这是使用它的一种方法 dplyr
:
library(reshape2)
library(dplyr)
M2 <- M %>%
melt(.) %>%
transmute(pair = paste(Var1, Var2, sep = ","),
value = value) %>%
filter(value > 0)
结果的顺序与您显示的不同,但我不清楚这对您是否重要。
library(tidyr)
M = as.data.frame(M)
M["rowid"] = row.names(M)
gather(M, colid, value, -rowid)
您不一定需要使用 apply()
循环。这是 base R 中的一个想法,它使用 which()
找到相关索引,然后进行一些简单的提取和组合。
wM <- which(M > 0, arr.ind = TRUE)
matrix(sort(paste(rownames(wM), colnames(M)[wM[,2]], sep = ",")))
# [,1]
# [1,] "A,B"
# [2,] "A,C"
# [3,] "B,C"
# [4,] "B,D"
# [5,] "C,A"
# [6,] "D,B"
# [7,] "D,C"
或者,您可以使用 row
和 col
代替 which
。
M0 <- M > 0
paste(rownames(M)[row(M)[M0]], colnames(M)[col(M)[M0]], sep = ",")
# [1] "C,A" "A,B" "D,B" "A,C" "B,C" "D,C" "B,D"
一种igraph
方法
library(igraph)
as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
graph_from_adjacency_matrix()
将矩阵作为输入,return 是一个图。使用weighted=TRUE
到return非零值作为权重。
as_data_frame
returns 具有关联属性的边列表(在本例中为权重)
所以对于你的例子,
as_data_frame(graph_from_adjacency_matrix(M, weighted = TRUE))
# from to weight
# 1 A B 1
# 2 A C 1
# 3 B C 1
# 4 B D 1
# 5 C A 1
# 6 D B 1
# 7 D C 1