【问题标题】:How to construct matrix from row/column vectors in Julia如何在 Julia 中从行/列向量构造矩阵
【发布时间】:2015-07-06 00:14:08
【问题描述】:

给定一个产生单列的函数/表达式,如何在 Julia 中从这些列构建矩阵?我尝试了以下(简化示例):

column(j) = [j, j, j]      # for example
my_matrix = Float64[column(j)[i] for i in 1:3, j in 1:4]

==> 3x4 Array{Float64,2}:
 1.0  2.0  3.0  4.0
 1.0  2.0  3.0  4.0
 1.0  2.0  3.0  4.0

结果是正确的,但这不是我想要的,因为列向量表达式被不必要地评估(每行一次)。

我也尝试过这种替代方法:

[column(j) for j in 1:4]

==> 4-element Array{Array{Float64,1},1}:
 [1.0,1.0,1.0]
 [2.0,2.0,2.0]
 [3.0,3.0,3.0]
 [4.0,4.0,4.0]

但我没有办法将其转换重塑成我想要的形式(二维矩阵而不是数组数组)。

如何在 Julia 中实现这一点?

【问题讨论】:

    标签: matrix julia


    【解决方案1】:

    你试过hcat吗?:

    julia> column(j) = [j, j ,j]
    column (generic function with 1 method)
    
    julia> my_matrix  = hcat([column(j) for j=1:4]...)
    3x4 Array{Int64,2}:
     1  2  3  4
     1  2  3  4
     1  2  3  4
    

    hcat in Julia docs

    【讨论】:

    • 这是完美的,谢谢!我知道 *cat 函数,但我不知道数组 => 通过省略号进行的解压缩元组转换。给其他 Julia 新手的建议:至少考虑查看最新版本的文档(即使使用旧版本的 Julia),有一些重大的一般改进(例如 THIS)。
    • 太好了,很高兴它对你有用。是的,手册变化很快,因此查看最新版本通常是个好主意。
    • 第二个维度很大怎么办?当j 运行到大于 200 万的值时,我会遇到段错误或堆栈溢出。
    【解决方案2】:

    但我没有办法将其转换重塑成我想要的形式(二维矩阵而不是数组数组)。

    您可以通过对列c的列向量的扁平化版本进行整形来获得矩阵:

    julia> column(j) = [j, j, j]
    column (generic function with 1 method)
    
    julia> c = [column(j) for j in 1:4]
    4-element Vector{Vector{Int64}}:
     [1, 1, 1]
     [2, 2, 2]
     [3, 3, 3]
     [4, 4, 4]
    
    julia> v = collect(Iterators.flatten(c))
    12-element Vector{Int64}:
     1
     1
     1
     2
     2
     2
     3
     3
     3
     4
     4
     4
    
    julia> m = reshape(v, 3, 4)
    3×4 Matrix{Int64}:
     1  2  3  4
     1  2  3  4
     1  2  3  4
    

    接受的答案建议的替代hcat(c...) 也可以,但正如评论所指出的,这不适用于大量列。 实际上,如果cn 列的向量,那么hcat(c...) 将编译带有n 参数的方法。这首先意味着如果您的代码对不同数量的列执行此操作,那么您每次都需要编译一个新方法。其次,编译参数过多的方法会导致栈内存溢出。

    因此,当您不需要单行解决方案时(例如,像上面结合 flatten 和 reshape 的解决方案),在我看来大多数 Julia 用户都这样做:

    m = Matrix{Int}(undef, 3, 4)
    for j in 1:4
        m[:, j] = column(j)
    end
    

    编辑 @Przemyslaw 提出了一个更好的解决方案:https://stackoverflow.com/a/68976092/1189815

    【讨论】:

    • 您的多线解决方案完全符合我的要求。遗憾的是,没有什么简洁的具有完全相同的语义(即没有对矩阵的冗余分配,也没有对列表达式的不必要的评估)。我决定不接受你的回答,因为原来的答案已经解决了我的问题......会给你赏金,但似乎我不能。
    • 感谢您的回复(即使是 6 年后)。我同意,遗憾的是没有一条线。我在许多包中都看到了...,所以我想在这里写一个替代解决方案来尝试传播这个词,以便人们意识到这种方法的问题。
    【解决方案3】:

    查看答案@Benoit 实际上使用reduce(hcat, c) 更快:

    julia> c = [[j,j,j] for j in 1:4]
    4-element Vector{Vector{Int64}}:
     [1, 1, 1]
     [2, 2, 2]
     [3, 3, 3]
     [4, 4, 4]
    
    
    julia> @btime reshape(collect(Iterators.flatten($c)), 3, 4)
      232.791 ns (6 allocations: 448 bytes)
    3×4 Matrix{Int64}:
     1  2  3  4
     1  2  3  4
     1  2  3  4
    
    julia> @btime reduce(hcat, $c)
      70.825 ns (1 allocation: 176 bytes)
    3×4 Matrix{Int64}:
     1  2  3  4
     1  2  3  4
     1  2  3  4
    

    【讨论】:

    猜你喜欢
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2020-06-25
    相关资源
    最近更新 更多