朱莉娅:当行号存储在数组中时,如何取消选择矩阵中的行

时间:2018-10-24 05:14:48

标签: julia

我想从矩阵A中删除行。

我要删除的行号存储在数组B中。

例如

B=[1,2,3]表示我要从矩阵A中删除第1、2和3行。我该如何用Julia语言来做到这一点?

2 个答案:

答案 0 :(得分:3)

如果您不想安装任何其他软件包,那么我知道的最新解决方案是:

x = randn(5, 2)
inds_to_remove = [1,3,4]
x[setdiff(1:size(x,1), inds_to_remove), :]

这个问题真正归结为如何反转一组已经提出并回答过here的索引。在链接的问题中,请注意,还有一个InvertedIndices软件包,可用于任意维的集合。

还值得注意的是,如果只想删除一行,那么:

x[1:end .!= i, :]

是一种快速,整洁的解决方案。

答案 1 :(得分:2)

另一种更快(但不太整齐)的可能性是

vcat(deleteat!([A[r,:]' for r in 1:size(A, 1)], inds)...)

即提取行作为向量,删除相关行,变换回矩阵形状。

示例:

julia> A = randn(5, 2)
5×2 Array{Float64,2}:
  0.0204771   0.641602
 -0.51661     0.0314303
 -0.0667214  -1.61672
 -0.303866    2.0537
 -1.31845    -1.44462

julia>     inds = [1,3,4]
3-element Array{Int64,1}:
 1
 3
 4

julia>     vcat(deleteat!([A[r,:]' for r in 1:size(A, 1)], inds)...)
2×2 Array{Float64,2}:
 -0.51661   0.0314303
 -1.31845  -1.44462

请注意,结果矩阵是一个副本,{@ {1}}尚未被修改,就像@ColinTBowers答案中一样。

基准:

A

在后者中,julia> @btime vcat(deleteat!([$(A)[r,:]' for r in 1:size($A, 1)], $inds)...); 405.335 ns (17 allocations: 912 bytes) julia> @btime $(A)[setdiff(1:size($A,1), 1:3), :]; # @ColinTBowers answer 5.049 μs (58 allocations: 2.16 KiB) 似乎是一个很大的瓶颈:

setdiff

手动实施

在速度上,应将以上所有内容与快速手动实施进行比较。类似于

julia> @btime setdiff(1:size($A,1), $inds)
  3.253 μs (40 allocations: 1.59 KiB)

这导致

rmrows(A, inds) = begin
  rows, cols = size(A)
  out = similar(A, rows-length(inds), cols)
  for c in 1:cols
    i = 1
    for r in 1:rows
      if !(r in inds)
         @inbounds out[i,c] = A[r,c]
         i+=1
      end
    end
  end
  out
end

Update1:​​手动实施

Update2:更快的手动实施