Julia 朱莉娅:当行号存储在数组中时,如何取消选择矩阵中的行
我想从矩阵Julia 朱莉娅:当行号存储在数组中时,如何取消选择矩阵中的行,julia,Julia,我想从矩阵a中删除行 我要删除的行号存储在数组B中 例如: B=[1,2,3]意味着我要从矩阵A中删除行1、2和3。如何使用Julia语言实现这一点?如果您不想安装任何其他软件包,那么我所知道的最新解决方案是: x = randn(5, 2) inds_to_remove = [1,3,4] x[setdiff(1:size(x,1), inds_to_remove), :] 这个问题归根结底是如何反转一组已经被问到和回答过的指数。从链接的问题中,请注意还有一个用于此的包,它将适用于任意维度的
a
中删除行
我要删除的行号存储在数组B
中
例如:
B=[1,2,3]
意味着我要从矩阵A
中删除行1、2和3。如何使用Julia语言实现这一点?如果您不想安装任何其他软件包,那么我所知道的最新解决方案是:
x = randn(5, 2)
inds_to_remove = [1,3,4]
x[setdiff(1:size(x,1), inds_to_remove), :]
这个问题归根结底是如何反转一组已经被问到和回答过的指数。从链接的问题中,请注意还有一个用于此的包,它将适用于任意维度的集合
还值得注意的是,如果您只想删除一行,那么:
x[1:end .!= i, :]
是一种快速、简洁的解决方案。另一种更快(但不那么简洁)的可能性是
vcat(deleteat!([A[r,:]' for r in 1:size(A, 1)], inds)...)
i、 e.提取行作为向量,删除相关行,转换回矩阵形状
示例:
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
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)
请注意,生成的矩阵是一个副本,a
没有被修改,就像@ColinTBowers answer中一样
基准测试:
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
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
这导致了
julia> @btime rmrows($A, $inds);
60.581 ns (1 allocation: 112 bytes)
更新1:手动执行
更新2:更快的手动实现我本来打算投票以的副本结束,但经过再三考虑,也许是因为OP是在问矩阵,而不是向量,这个问题完全不同,不可能是副本。是的,invertedices.jl使这只是一个[not(B),:]但你们喜欢基本的Julia答案,对吗?@ColinTBowers如果您想从向量中删除行(即元素),只需执行
deleteat!(vec,inds)
。这很整洁(!),但不幸的是没有表现出来。请参阅下面的我的基准。@crstnbr请参阅我对您的基准的反驳:-)我认为您可以在手动实现中按列操作,获得更快的解决方案,尤其是对于更大尺寸的阵列。可能还有其他一些优化(如果inds
大于矩阵大小的一半,则首先将其反转,以便在for循环中更快地搜索if
)。因此,考虑到包开发人员(可能)自己做这种优化,选择包通常是最好的选择。@hckr同意。我只是想得到一个粗略的估计手动实现。伟大的答案!然而,请注意,对于这个问题,算法效率高度依赖于输入的大小。在我的机器上,当您真正放大问题时,setdiff
方法很容易占主导地位,例如尝试删除10000行、500列和500行。