我想从带有名字的矢量创建一个矩阵。其中列名是元素的名称,如果某些名称不在向量中,则对应的元素将为NA(或0)。
一个简单的例子是这样的:
set.seed(1)
vec_a <- rnorm(10)
names(vec_a) <- sample(letters, 10)
vec_b <- rnorm(10)
names(vec_b) <- sample(letters, 10)
vec_c <- rnorm(10)
names(vec_c) <- sample(letters, 10)
vec_d <- rnorm(10)
names(vec_d) <- sample(letters, 10)
example_matrix <- bind_rows(vec_a, vec_b, vec_c, vec_d)
example_matrix
## # A tibble: 4 x 24
## y f p c z i a h
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 -0.6264538 0.1836433 -0.8356286 1.5952808 0.3295078 -0.8204684 0.4874291 0.73832471
## 2 NA 0.8212212 NA 0.9189774 NA NA NA NA
## 3 NA NA NA -0.0593134 NA NA NA -0.05380504
## 4 NA NA NA NA -0.7074952 0.7685329 0.3981059 NA
## # ... with 16 more variables: x <dbl>, v <dbl>, m <dbl>, k <dbl>, b <dbl>, g <dbl>, j <dbl>,
## # l <dbl>, t <dbl>, r <dbl>, q <dbl>, e <dbl>, o <dbl>, u <dbl>, s <dbl>, d <dbl>
我知道bind_rows()
有效,example_matrix
是我想要的。
问题是如果向量变大,这个过程可能会很慢。
再举一个例子:
all_names <- do.call(paste0, replicate(5, sample(LETTERS, 1e4, TRUE), FALSE))
n <- 5e3
vec_a <- rnorm(n)
names(vec_a) <- sample(all_names, n)
vec_b <- rnorm(n)
names(vec_b) <- sample(all_names, n)
tmp <- bind_rows(vec_a, vec_b) # works, but slow
这已经很慢了,我的数据比这大(50K唯一名称,每个向量有10K-30K元素)。
我想创建名称的整数索引并构造一个直接赋值(i,j,x)的稀疏矩阵,但不确定构造这些索引的最简单方法是什么。
所以问题是什么是快速创建这个矩阵的方法?欢迎提出任何建议。
答案 0 :(得分:2)
您可以尝试使用rbindlist
包中的data.table
功能。参见示例。
require(data.table)
require(dplyr)
all_names <- unique(do.call(paste0, replicate(5, sample(LETTERS, 1e4, TRUE), FALSE)))
anyDuplicated(all_names)
n <- 5e3
vec_a <- rnorm(n)
names(vec_a) <- sample(all_names, n)
vec_b <- rnorm(n)
names(vec_b) <- sample(all_names, n)
length(union(names(vec_a), names(vec_b)))
system.time(tmp1 <- bind_rows(vec_a, vec_b))
system.time(tmp2 <- rbindlist(list(as.list(vec_a), as.list(vec_b)), fill = T))
all.equal(tmp1, tmp2)
输出:
> system.time(tmp1 <- bind_rows(vec_a, vec_b))
user system elapsed
3.20 0.00 3.21
> system.time(tmp2 <- rbindlist(list(as.list(vec_a), as.list(vec_b)), fill = T))
user system elapsed
0.01 0.00 0.01
> all.equal(tmp1, tmp2)
[1] TRUE