创建所有非零元素都设置为 1 的新矩阵 (julia)
Create new matrix with all non-zero elements set to ones (julia)
我想要一种有效(矢量化)的方式来将 julia 中的矩阵操作为新矩阵,其中所有非零元素都是新矩阵中的元素。
比如我想要这个矩阵
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
成为
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
最简单的方法是将此矩阵转换为 BitMatrix
矩阵,如下所示:
julia> x = [0 3 6 8 0
7 0 2 0 1
0 4 9 1 0]
3×5 Matrix{Int64}:
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
julia> x .!= 0
3×5 BitMatrix:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
如果您希望矩阵包含 Int
个值,那么您可以这样做:
julia> Int.(x .!= 0)
3×5 Matrix{Int64}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
最后,如果您的 0
值具有混合类型,并且您希望“按原样”保留它们,那么您可以这样做:
julia> x = Real[0 3 6 8 UInt8(0)
7 0 2 0 1
0.0 4 9 1 0]
3×5 Matrix{Real}:
0 3 6 8 0x00
7 0 2 0 1
0.0 4 9 1 0
julia> @. ifelse(iszero(x), x, 1)
3×5 Matrix{Real}:
0 1 1 1 0x00
1 0 1 0 1
0.0 1 1 1 0
除了广播,你还可以使用理解,它也应该很快。例如
julia> [v == 0 ? v : 1 for v in x]
3×5 Matrix{Real}:
0 1 1 1 0x00
1 0 1 0 1
0.0 1 1 1 0
或例如
julia> [ifelse(v == 0, 0, 1) for v in x]
3×5 Matrix{Int64}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
尚未提及的替代方法是使用 map
:
julia> x = [0 3 6 8 0
7 0 2 0 1
0 4 9 1 0]
3×5 Matrix{Int64}:
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
julia> map(!=(0), x)
3×5 Matrix{Bool}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
请注意 !=(0)
等同于 y -> y != 0
。
正如另一个答案所示,广播布尔值函数的结果是 BitMatrix
。使用 map
可以避免这种情况。
如果您想要一个生成与输入相同类型的“0”和“1”的解决方案:
julia> map(y -> ifelse(y == zero(y), one(y), zero(y)), x)
3×5 Matrix{Int64}:
1 0 0 0 1
0 1 0 1 0
1 0 0 0 1
julia> map(y -> ifelse(y == zero(y), one(y), zero(y)), Float64.(x))
3×5 Matrix{Float64}:
1.0 0.0 0.0 0.0 1.0
0.0 1.0 0.0 1.0 0.0
1.0 0.0 0.0 0.0 1.0
我想要一种有效(矢量化)的方式来将 julia 中的矩阵操作为新矩阵,其中所有非零元素都是新矩阵中的元素。
比如我想要这个矩阵
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
成为
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
最简单的方法是将此矩阵转换为 BitMatrix
矩阵,如下所示:
julia> x = [0 3 6 8 0
7 0 2 0 1
0 4 9 1 0]
3×5 Matrix{Int64}:
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
julia> x .!= 0
3×5 BitMatrix:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
如果您希望矩阵包含 Int
个值,那么您可以这样做:
julia> Int.(x .!= 0)
3×5 Matrix{Int64}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
最后,如果您的 0
值具有混合类型,并且您希望“按原样”保留它们,那么您可以这样做:
julia> x = Real[0 3 6 8 UInt8(0)
7 0 2 0 1
0.0 4 9 1 0]
3×5 Matrix{Real}:
0 3 6 8 0x00
7 0 2 0 1
0.0 4 9 1 0
julia> @. ifelse(iszero(x), x, 1)
3×5 Matrix{Real}:
0 1 1 1 0x00
1 0 1 0 1
0.0 1 1 1 0
除了广播,你还可以使用理解,它也应该很快。例如
julia> [v == 0 ? v : 1 for v in x]
3×5 Matrix{Real}:
0 1 1 1 0x00
1 0 1 0 1
0.0 1 1 1 0
或例如
julia> [ifelse(v == 0, 0, 1) for v in x]
3×5 Matrix{Int64}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
尚未提及的替代方法是使用 map
:
julia> x = [0 3 6 8 0
7 0 2 0 1
0 4 9 1 0]
3×5 Matrix{Int64}:
0 3 6 8 0
7 0 2 0 1
0 4 9 1 0
julia> map(!=(0), x)
3×5 Matrix{Bool}:
0 1 1 1 0
1 0 1 0 1
0 1 1 1 0
请注意 !=(0)
等同于 y -> y != 0
。
正如另一个答案所示,广播布尔值函数的结果是 BitMatrix
。使用 map
可以避免这种情况。
如果您想要一个生成与输入相同类型的“0”和“1”的解决方案:
julia> map(y -> ifelse(y == zero(y), one(y), zero(y)), x)
3×5 Matrix{Int64}:
1 0 0 0 1
0 1 0 1 0
1 0 0 0 1
julia> map(y -> ifelse(y == zero(y), one(y), zero(y)), Float64.(x))
3×5 Matrix{Float64}:
1.0 0.0 0.0 0.0 1.0
0.0 1.0 0.0 1.0 0.0
1.0 0.0 0.0 0.0 1.0