【发布时间】:2017-12-13 11:32:09
【问题描述】:
假设我们有以下三个向量。
L = c("1", "3")
K = c("2", "9", "2:9")
S = c("7")
有没有办法将它们组合成一个类似于上面的矩阵?
L K S
1 0 0
3 0 0
0 2 0
0 9 0
0 2:9 0
0 0 7
谢谢。
【问题讨论】:
假设我们有以下三个向量。
L = c("1", "3")
K = c("2", "9", "2:9")
S = c("7")
有没有办法将它们组合成一个类似于上面的矩阵?
L K S
1 0 0
3 0 0
0 2 0
0 9 0
0 2:9 0
0 0 7
谢谢。
【问题讨论】:
library(dplyr)
L = c("1", "3")
K = c("2", "9", "2:9")
S = c("7")
Ltable <- tibble(L=L)
Ktable <- tibble(K=K)
Stable <- tibble(S=S)
JoinedMatrix <- Ltable %>% bind_rows(Ktable) %>% bind_rows(Stable) %>% as.matrix()
JoinedMatrix[which(is.na(JoinedMatrix))] <- "0"
bind_rows from dplyr 允许您将数据帧(或小标题)绑定在一起。由于三个 tibbles 具有不同名称的列,因此它们在连接后保留为不同的列,用NA 填充缺失的字段。之后,我们只需将所有NAs 替换为0,就完成了。
> JoinedMatrix
L K S
[1,] "1" "0" "0"
[2,] "3" "0" "0"
[3,] "0" "2" "0"
[4,] "0" "9" "0"
[5,] "0" "2:9" "0"
[6,] "0" "0" "7"
【讨论】:
这是一个想法。首先我们创建一个包含所有向量的列表,然后创建一个矩阵,其行数等于向量的所有元素的总和,列数等于向量的数量。然后我们使用mapply 将(我们的列表中的)第一个向量的元素与矩阵的第一列相匹配。分别与第二个和第三个向量和列相同。然后我们使用它(一个逻辑矩阵)将矩阵中所有剩余的不匹配元素转换为 0。
l1 <- list(L, K, S)
m1 <- matrix(unlist(l1), nrow = sum(lengths(l1)), ncol = length(l1))
m1[!mapply(`%in%`, as.data.frame(m1), l1)] <- 0
m1
# [,1] [,2] [,3]
#[1,] "1" "0" "0"
#[2,] "3" "0" "0"
#[3,] "0" "2" "0"
#[4,] "0" "9" "0"
#[5,] "0" "2:9" "0"
#[6,] "0" "0" "7"
为了解决您的评论并将其升级为也适用于出现在多个向量中的相同值,我们遵循相同的逻辑,但我们根据每个向量的累积序列对矩阵每一列的索引执行此操作。由于这有点复杂,我们可以将它全部放在一个接受向量列表作为输入的函数中,即
create_mat <- function(list){
m1 <- matrix(unlist(list), nrow = sum(lengths(list)), ncol = length(list))
m2 <- matrix(seq(nrow(m1)), ncol = ncol(m1), nrow = nrow(m1))
l2 <- lapply(lengths(list), seq)
v2 <- c(0, head(cumsum(lengths(list)), -1))
l2 <- Map(`+`, l2, v2)
m1[!mapply(`%in%`, as.data.frame(m2), l2)] <- 0
return(m1)
}
# Test with some values being same for multiple vectors,
M = c("1", "3")
N = c("1", "9", "2:9")
P = c("3")
create_mat(list(M, N, P))
# [,1] [,2] [,3]
#[1,] "1" "0" "0"
#[2,] "3" "0" "0"
#[3,] "0" "1" "0"
#[4,] "0" "9" "0"
#[5,] "0" "2:9" "0"
#[6,] "0" "0" "3"
【讨论】:
g = as.list(data.frame(m1)) expand.grid(g)
unique(expand.grid(g)) 并工作了。
c("0") 而另一个有大约 16000 个元素 c(1:16000) ,通过执行此函数,您会耗尽系统的内存R 得到一个致命错误。您是否认为有一种方法可以使其对资源更加友好? P.S 我在 4GB 内存的 PC 上运行它
这是另一种方法:首先创建一个 0 矩阵,然后使用两个索引向量 k 和 1:l,在正确的位置输入值。
l = length(c(L,K,S))
k = rep(1:3,times=c(length(L),length(K),length(S)))
m = matrix(0,ncol=3,nrow=l)
m[cbind(1:l,k)] = c(L,K,S)
[,1] [,2] [,3]
[1,] "1" "0" "0"
[2,] "3" "0" "0"
[3,] "0" "2" "0"
[4,] "0" "9" "0"
[5,] "0" "2:9" "0"
[6,] "0" "0" "7"
编辑:对于可以更好地泛化到更多输入向量的版本,根据@DavidArenburg 的评论,您可以这样做:
l = list(L,K,S)
len = length(unlist(l))
k = rep(seq_along(l), lengths(l))
m = matrix(0, nrow=len, ncol=length(l))
m[cbind(1:len, k)] = unlist(l)
【讨论】: