问题:当用单行构建矩阵时,Julia 将它们解释为列。
a = [1 2 3; 4 5 6; 7 8 9]
3×3 Array{Int64,2}:
1 2 3
4 5 6
7 8 9
b = [a[1:2,:]; a[1:2,:]] # Rows duplicated correctly
4×3 Array{Int64,2}:
1 2 3
4 5 6
1 2 3
4 5 6
c = [a[1,:]; a[1,:]] # Rows converted to columns
6-element Array{Int64,1}:
1
2
3
1
2
3
如何解决这个问题?
解决方案:虽然感觉有点费解,但这是因为类型从矩阵变成了向量。为了保持类型相同,您需要以与示例中第二行代码类似的方式从所需的行选择到所需的行。
c = [a[1:1,:]; a[1:1,:]]
2×3 Array{Int64,2}:
1 2 3
1 2 3
除了范围索引之外,您还可以转置向量
julia> [a[1, :]'; a[1, :]']
2×3 Array{Int64,2}:
1 2 3
1 2 3
看起来这种方法比范围索引性能更高,但应该在更大的矩阵上进行测试,而且如果您有范围和单列,它也不一致
using BenchmarkTools
f1(a) = [a[1:1,:]; a[1:1,:]]
f2(a) = [a[1, :]'; a[1, :]']
julia> @btime f1($a)
122.440 ns (3 allocations: 352 bytes)
2×3 Array{Int64,2}:
1 2 3
1 2 3
julia> @btime f2($a)
107.480 ns (3 allocations: 352 bytes)
2×3 Array{Int64,2}:
1 2 3
1 2 3
这里的根本问题与
a
如何被索引以及索引操作返回什么有关。来自 Julia docs 关于索引数组的内容:
所有用标量索引的维度都将被删除。
:
运算符产生一个范围,即索引向量。所以,举个例子,
julia> a[1,:]
3-element Vector{Int64}:
1
2
3
julia> a[1:1,:]
1×3 Matrix{Int64}:
1 2 3
所以构造
c
的正确方法是
julia> c = [a[1:1,:]; a[1:1,:]]
2×3 Matrix{Int64}:
1 2 3
1 2 3
如其他答案之一所述。使用
'
运算符转置 a[1,:]
是不正确的,因为 '
实际上是伴随运算(复数转置)。它适用于真实矩阵,但不适用于复杂矩阵:
julia> a[1,:]'
1×3 adjoint(::Vector{Int64}) with eltype Int64:
1 2 3
julia> a = [1+1im 2+2im 3+3im; 4+4im 5+5im 6+6im; 7+7im 8+8im 9+9im]
3×3 Matrix{Complex{Int64}}:
1+1im 2+2im 3+3im
4+4im 5+5im 6+6im
7+7im 8+8im 9+9im
julia> a[1,:]'
1×3 adjoint(::Vector{Complex{Int64}}) with eltype Complex{Int64}:
1-1im 2-2im 3-3im
julia> a[1:1,:]
1×3 Matrix{Complex{Int64}}:
1+1im 2+2im 3+3im