我有一个有趣的挑战:我试图从整数向量构造一个二进制矩阵。二进制矩阵应包含与向量长度一样多的行,以及与整数向量中的最大值一样多的列。矩阵中的第i行将对应于向量的第i个元素,其中行在位置j处包含1,其中j等于向量的第i个元素的值;否则,该行包含零。如果第i个整数的值为0,那么整个第i行应为0。
为了使这更简单,这是一个可重复的例子:
set.seed(1)
playv<-sample(0:5,20,replace=TRUE)#sample integer vector
playmat<-matrix(playv,nrow=length(playv),ncol=max(playv))#create matrix from vector
for (i in 1:length(playv)){
pos<-as.integer(playmat[i,1])
playmat[i,pos]<-1
playmat[i,-pos]<-0}
head(playmat)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 0 1 0 0 0
[3,] 0 0 1 0 0
[4,] 0 0 0 0 1
[5,] 1 0 0 0 0
[6,] 0 0 0 0 1
上述解决方案是正确的,我只是想做一些更健壮的事情。
答案 0 :(得分:4)
当然,您也可以使用table
:
> table(sequence(length(playv)), playv)
playv
0 1 2 3 4 5
1 0 1 0 0 0 0
2 0 0 1 0 0 0
3 0 0 0 1 0 0
4 0 0 0 0 0 1
5 0 1 0 0 0 0
6 0 0 0 0 0 1
7 0 0 0 0 0 1
8 0 0 0 1 0 0
9 0 0 0 1 0 0
10 1 0 0 0 0 0
11 0 1 0 0 0 0
12 0 1 0 0 0 0
13 0 0 0 0 1 0
14 0 0 1 0 0 0
15 0 0 0 0 1 0
16 0 0 1 0 0 0
17 0 0 0 0 1 0
18 0 0 0 0 0 1
19 0 0 1 0 0 0
20 0 0 0 0 1 0
如果速度是一个问题,我会建议手动方法。首先,确定向量中的唯一值。其次,创建一个空矩阵来填充。第三,使用矩阵索引来识别应该填充的位置为1。
像这样:
f3 <- function(vec) {
U <- sort(unique(vec))
M <- matrix(0, nrow = length(vec),
ncol = length(U),
dimnames = list(NULL, U))
M[cbind(seq_len(length(vec)), match(vec, U))] <- 1L
M
}
用法为f3(playv)
。
将其添加到基准测试中,我们得到:
library(microbenchmark)
microbenchmark(f1(v), f2(v), f3(v), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# f1(v) 2104.4808 3151.4308 3314.8173 3344.6696 4023.5246 10
# f2(v) 3956.5678 4782.7863 5994.4448 6320.1901 6646.0405 10
# f3(v) 486.4406 574.1133 746.9112 927.3407 987.9121 10
答案 1 :(得分:3)
set.seed(1)
playv <- sample(0:5,20,replace=TRUE)
playv <- as.character(playv)
results <- model.matrix(~playv-1)
您可以重命名result
中的列。
我喜欢Ananda Mahto提供的解决方案,并将其与model.matrix
进行比较。这是一个代码
library(microbenchmark)
set.seed(1)
v <- sample(1:10,1e6,replace=TRUE)
f1 <- function(vec) {
vec <- as.character(vec)
model.matrix(~vec-1)
}
f2 <- function(vec) {
table(sequence(length(vec)), vec)
}
microbenchmark(f1(v), f2(v), times=10)
model.matrix
比table
Unit: seconds
expr min lq median uq max neval
f1(v) 2.890084 3.147535 3.296186 3.377536 3.667843 10
f2(v) 4.824832 5.625541 5.757534 5.918329 5.966332 10