我有一个矩阵,有很多行和列
x <- matrix(c(1, 1, 3, 3, 55, 55, 1, 3, 3, 1,
1, 1, 3, 3, 55, 55, 1, 3, 9, 1), ncol = 2)
使用
x[!duplicated(x, MARGIN = 1), ]
我想确定原始矩阵中每一行的第一次出现:这里有向量
1 1 3 3 5 5 1 3 9 1
我想出的最好的方法是使用既不高效也不优雅的循环的复杂和迂回的方法。我也知道data.frames的可能解决方案;那些涉及将行连接到字符串中的解决方案也是相当资源密集型的。
有没有使用基本R的优雅解决方案?
# Identify duplicates
duplicate <- duplicated(x, MARGIN = 1)
# Identify first occurrence of each duplicate
firstDup <- duplicated(x, MARGIN = 1, fromLast = TRUE) & !duplicate
indices <- which(firstDup)
# Initialize index for unique rows
index <- seq_len(dim(x)[1])
cf <- duplicate
for (i in indices) {
# Duplicates must occur after first occurrence
cf[seq_len(i)] <- FALSE
dups <- apply(x[cf, , drop = FALSE], 1L, identical, x[i, ])
index[which(cf)[dups]] <- i
}
index
@MikaelJagan的答案基于asplit
和匹配(
列表匹配可能非常缓慢,最好避免,除非是在简单的情况下。
在这里,我们比较了他们的
asplit
答案与其他基本R答案的性能:
@Onyanbu的答案基于粘贴
@汤玛西斯科的答案基于互动
作为比较点,我们将这些与两个非基准R答案一起进行基准测试(认识到OP只要求基准R):
@MikaelJagan的Rcpp
答案,与其他答案不同之处在于避免了矩阵x
的副本
library("microbenchmark")
library("data.table")
data.table 1.14.2 using 4 threads (see ?getDTthreads). Latest news: r-datatable.com
f_asplit <- function(x) {
l <- asplit(x, 1L)
match(l, l)
}
f_paste <- function(x) {
s <- do.call(paste, as.data.frame(x))
match(s, s)
}
f_interaction1 <- function(x) {
z <- as.integer(interaction(as.data.frame(x)))
ave(seq_along(z), z, FUN = function(x) x[1L])
}
f_interaction2 <- function(x) {
z <- as.integer(interaction(as.data.frame(x)))
match(z, z)
}
f_join <- function(x) {
d <- as.data.table(x)
d[d, on = names(d), mult = "first", which = TRUE]
}
Rcpp::sourceCpp('<copy source code from @MikaelJagan\'s answer here>')
bm <- function(x, times) {
microbenchmark(
f_asplit(x),
f_paste(x),
f_interaction1(x),
f_interaction2(x),
f_join(x),
match_row(x),
times = times,
check = "identical",
setup = gc(FALSE)
)
}
我们首先评估了
5e 06
-by-2整数矩阵的性能:
set.seed(1L)
x <- matrix(sample(10L, size = 1e+07L, replace = TRUE), ncol = 2L)
bm(x, times = 10L)
Unit: milliseconds
expr min lq mean median uq max neval
f_asplit(x) 16637.5798 18733.3617 19013.3497 18782.1677 18838.6351 23053.6849 10
f_paste(x) 504.7293 506.9240 508.1568 507.4751 509.3188 512.8925 10
f_interaction1(x) 403.5811 406.8908 412.0491 408.4909 409.9671 431.4656 10
f_interaction2(x) 233.4562 234.1044 241.6112 235.8503 236.9662 295.3077 10
f_join(x) 114.2941 114.6058 117.4835 115.3864 119.4647 128.0236 10
match_row(x) 460.6730 464.8487 467.1219 467.5593 469.2787 472.8399 10
基于
asplit
的答案确实比基本R选项慢了很多。基于交互
的答案是快速的(使用匹配
比使用ave
更快),甚至可以与使用data.table
和4个OpenMP线程的答案相媲美,这是最快的。
上述结果不能推广到所有矩阵输入,部分原因是基于
交互作用的函数与
ncol(x)
的伸缩性较差:如果x
的每列都有u
唯一元素,则可能的交互作用数为u^ncol(x)
。基于paste
的函数似乎更健壮。
在第二组计时中,我们使用了行数较少(
5e 05
)列数较多(20)的矩阵。在使用“简单”系统的初始运行中。时间
,f_交互1
和f_交互2
均出错:
set.seed(1L)
x <- matrix(sample(10L, size = 1e+07L, replace = TRUE), ncol = 20L)
system.time(f_interaction1(x))
# Error: cannot allocate vector of size 7.5 Gb
# Timing stopped at: 328.8 29.05 379.9
system.time(f_interaction2(x))
# Error: cannot allocate vector of size 7.5 Gb
# Timing stopped at: 173.2 6.05 200.4
其余函数都可以处理
5e 05
-by-20整数矩阵,并使用microbenchmark
进行进一步评估:
microbenchmark(
f_asplit(x),
f_paste(x),
f_join(x),
match_row(x),
times = 10L,
check = "identical",
setup = gc(FALSE)
)
# still running...
如果你有大矩阵,那么下面的解决方案可能就足够了:
l <- do.call(paste, data.frame(x))
match(l, l)
[1] 1 1 3 3 5 5 1 3 9 1
这个怎么样?
l <- asplit(x, 1L)
match(l, l)
[1] 1 1 3 3 5 5 1 3 9 1
这里,我们使用asplit
获取x
行的列表l
,并使用match
获取每行第一次出现的索引。
为了简单起见,我将column称为col。为什么矩阵是[行,列]而不是[列,行]?这给我带来了很多头痛和困惑。 我的思路是这样的:1.一个正则数组, 就像一个矩阵,有一行和多列。它的符号是这样的:啊,如果我们有另一个维度, 现在有行了。因此,让我们在'n',arr[n,rows]之后记下这些行,但现实告诉我们,情况并非如此。 对不起,如果我混淆了你,对不起我的无知。
中的值匹配功能非常有用。但据我理解,它不足以支持二维或高维输入。 例如,假设和是相同列数的矩阵,我想将的行与的行进行匹配。“R”函数调用不这样做。列表的输入也存在同样的不足。 我已经实现了我自己的版本,名为(附在下面),但我想知道您对此任务的解决方案是什么。
我有两个列表,每个列表中有两个矩阵。。是否有一种方法可以对它们进行矩阵计算,即相加,其中matrix1中的蓝色矩阵与matrix2中的蓝色矩阵相加,matrix1中的红色矩阵与matrix2中的红色矩阵相加。我能想到的唯一方法是在循环中进行计算 请注意,我将有大约10个,以及不止一组(即蓝色、红色、绿色、紫色)
我不是高级R用户。我主要用它来进行矩阵代数计算。我有一个大矩阵(9400×9400;675.1MB),我想反转。我尝试了“解决”函数和“胆量2inv”,我得到了“错误在......‘a’一定是一个复杂的矩阵”。我也尝试了从MASS包的ginv函数,我得到了错误消息在svd(X)错误:无限或丢失值在'x'。我确信我的矩阵没有空(全零)列或行。我检查了使用:从数据框中删除具有零值的列,我得到了相同的矩
我正在实现一个稀疏矩阵类,使用映射向量来存储数据(映射表示矩阵的一行,其中键是列的索引,值是该位置的maitrix的值)我已经编写了计算行列式的函数,但我不知道是否有一种方法可以计算这种节省的时间(因为矩阵是稀疏的,大多数值为零)在这里我的实现: 这是类接口 我计算行列式的方式是什么?假设运算符()以这种方式重载 提前感谢您的帮助
我有一个非常大的100000左右的平方矩阵,我想知道这个矩阵的行列式值是否为零。 最快的方法是什么? 我必须在C中实现它