将数组作为列追加到预初始化的矩阵

时间:2019-05-04 12:43:30

标签: julia

我希望使用索引将数组的结果填充到预初始化的矩阵中,以进行循环输出:

  A = Float64.(reshape(1.0:81.0,9,9))
  # initialize output
  B = zeros(Int64, 2, 9)
  j = 1
  for j in 1:size(A,2) # loop cols
    out = [sum(A[:,j]),j]
    out = reshape(out,2,1) # make column to append
    # append out to the B
    global B = hcat(B,out) # this grows...
  end

我初始化了B = zeros(Int64, 2, 9)

sum操作的预期输出一样暗淡。

在我的真实示例中-我遍历j,列和i行-然后输出是一个数组...而不是使用hcat()将数组附加到我的输出中,我可以这样做吗索引?

在上面,它使用hcat()并将其附加到现有的B上以使其增长。此后,我尝试使用第2行和cols 0进行Initializg,因此hcat()构建为纠正输出暗淡:

B = zeros(Int64, 2, 0)

我怀疑hcat()是否会提高内存效率(例如,使用global来代替)-如果我无法通过索引做到这一点,则可以在[i,j]处为另一个内部循环填充它。但是也许有人可以将数组作为列追加到现有的预初始化输出中?

1 个答案:

答案 0 :(得分:2)

建议预先分配B,然后再填写。我将代码包装在一个函数中,因为它简化了基准测试:

function f2()
    A = reshape(1:81,9,9)
    B = zeros(Int64, 2, 9 + size(A,2))
    for j in 1:size(A,2) # loop cols
        B[:, j + 9] .= (sum(view(A, :, j)), j)
    end
    B
end

您的旧代码是:

function f1()
    A = Float64.(reshape(1.0:81.0,9,9))
    B = zeros(Int64, 2, 9)
    j = 1
    for j in 1:size(A,2) # loop cols
        out = [sum(A[:,j]),j]
        out = reshape(out,2,1) # make column to append
        # append out to the B
        B = hcat(B,out)
    end
    B
end

这是一个比较:

julia> @btime f1()
  8.567 μs (83 allocations: 7.72 KiB)
2×18 Array{Float64,2}:
 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  45.0  126.0  207.0  288.0  369.0  450.0  531.0  612.0  693.0
 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0   1.0    2.0    3.0    4.0    5.0    6.0    7.0    8.0    9.0

julia> @btime f2()
  73.662 ns (1 allocation: 368 bytes)
2×18 Array{Int64,2}:
 0  0  0  0  0  0  0  0  0  45  126  207  288  369  450  531  612  693
 0  0  0  0  0  0  0  0  0   1    2    3    4    5    6    7    8    9

您会发现差异非常明显。

您的原始代码还有一些次要注释:

  • 无需在Float64.上调用reshape(1.0:81.0,9,9),该对象已经包含具有Float64值的元素
  • 在您的代码中,最初B持有Int64A持有Float64时存在不一致的地方-我做到了这一点(我选择了Int64,但同样可以使用Float64
  • sum(A[:,j])不必要地分配了新对象;使用view
  • 更快
  • 您不必在reshape(out,2,1)之前在out上调用hcat,因为矢量已被视为柱状对象