I'd like to filter each row of my matrix a
such that each row contains non-negative values.
First, I tried this:
julia> a = [-1 2 3; 4 5 6; -5 3 4; 3 5 5]
4×3 Matrix{Int64}:
-1 2 3
4 5 6
-5 3 4
3 5 5
julia> # Desired Operation after filtering should yield 2x3 matrix, [4 5 6; 3 5 5]
julia> mask1 = a .>= 0
4×3 BitMatrix:
0 1 1
1 1 1
0 1 1
1 1 1
julia> a[mask1]
10-element Vector{Int64}:
4
3
2
5
3
5
3
6
4
5
This first attempt flattens my matrix. The same thing happens when I do a[mask1, :].
My second attempt I tried this (the equivalent logic works using python's numpy):
julia> mask2 = minimum(a, dims=2) .>= 0
4×1 BitMatrix:
0
1
0
1
julia> a[mask2, :]
2×1 Matrix{Int64}:
4
3
My second attempt only captures the first element of the second and fourth rows, when I want the entire second and fourth rows. Note that if I use the equivalent boolean array for mask2, I do get the desired result:
julia> mask3 = [false; true; false; true]
4-element Vector{Bool}:
0
1
0
1
julia> a[mask3, :]
2×3 Matrix{Int64}:
4 5 6
3 5 5
So, is the idiomatic way to do this row by row filtering to cast BitMatrix to a Vector{Bool}, or is there a cleaner way? Additionally, the crux of the question is why BitMatrix only returns one element of one row while Vector{Bool} returns the entire row.
One possible way:
julia> a[[all(row.>=0) for row in eachrow(a)], :]
2×3 Matrix{Int64}:
4 5 6
3 5 5
Another one:
julia> a[findall(x->all(x .>=0), eachrow(a)), :]
2×3 Matrix{Int64}:
4 5 6
3 5 5
The version with minimum
you were trying to do would be:
julia> a[minimum.(eachrow(a)) .>= 0, :]
2×3 Matrix{Int64}:
4 5 6
3 5 5
or following @DNF suggestion which is actually the best:
julia> a[all.(>=(0), eachrow(a)), :]
2×3 Matrix{Int64}:
4 5 6
3 5 5