如何在Julia中将Array {Array {Float64,1},1}转换为矩阵?

5

假设我有这样的输入:

> [[0.8681299566762923,-0.3472589826095631], [3.2300860990307445,3.3731249077464946]]

我应该如何将其转换为更加舒适的类型,如矩阵(知道尺寸)?

2个回答

8
你可以使用展开运算符(...)和hcat来实现你想要的效果:
julia> a = Vector[[0.8681299566762923,-0.3472589826095631], [3.2300860990307445,3.3731249077464946]]
2-element Array{Array{T,1},1}:
 [0.8681299566762923,-0.3472589826095631]
 [3.2300860990307445,3.3731249077464946]

julia> hcat(a...)
2x2 Array{Float64,2}:
  0.86813   3.23009
 -0.347259  3.37312

如果您想将堆栈停止成行而非列,则可以执行以下操作:
julia> vcat(map(x->x', a)...)
2x2 Array{Float64,2}:
 0.86813  -0.347259
 3.23009   3.37312

我不建议逐行构建Matrix,因为这与Julia的列主数组布局相冲突。对于较大的矩阵,堆叠作为列并转置输出实际上更有效:

julia> a2 = Vector{Float64}[rand(10) for i=1:5000];

julia> stackrows1{T}(a::Vector{Vector{T}}) = vcat(map(transpose, a)...)::Matrix{T}
stackrows1 (generic function with 2 methods)

julia> stackrows2{T}(a::Vector{Vector{T}}) = hcat(a...)'::Matrix{T}
stackrows2 (generic function with 2 methods)

julia> stackrows1(a2) == stackrows2(a2)  # run once to compile and make sure functions do the same thing
true

julia> @time for i=1:100 stackrows1(a2); end
elapsed time: 0.142792896 seconds (149 MB allocated, 7.85% gc time in 7 pauses with 0 full sweep)

julia> @time for i=1:100 stackrows2(a2); end
elapsed time: 0.05213114 seconds (88 MB allocated, 12.60% gc time in 4 pauses with 0 full sweep)

这比我的方法好多了。+1 - Colin T Bowers
非常感谢,我想到了先使用flatten再使用reshape的解决方案,但是它很慢且不美观。 - Piotr Gródek
1
在 Julia 1.0 中,您可以通过 reduce(hcat, x)transpose(reduce(hcat, x)) 分别获得更好的性能。 - Bogumił Kamiński

0
对于一个通用函数,它可以在大多数情况下工作,如果出现问题则抛出错误,并允许您选择输出矩阵的形状,我很难想出比以下解决方案更聪明的东西(尽管看起来不太优雅):
function toMatrix{T<:Any}(x::Vector{Vector{T}}, dim::Int=1)
    if length(x) == 0
        return(Array(T, 0, 0))
    else
        N = length(x[1])
        M = length(x)
        if dim == 1
            xMat = Array(T, N, M)
            for m = 1:M
                if length(x[m]) != N
                    error("Conversion not possible due to vector length mismatch")
                end
                for n = 1:N
                    xMat[n, m] = x[m][n]
                end
            end
        elseif dim == 2
            xMat = Array(T, M, N)
            for m = 1:M
                if length(x[m]) != N
                    error("Conversion not possible due to vector length mismatch")
                end
                for n = 1:N
                    xMat[m, n] = x[m][n]
                end
            end         
        else
            error("Invalid dimension argument")
        end
        return(xMat)
    end
end

我很想看看其他用户能提出什么解决方案。我确实不知道在Base中是否有一个函数可以满足你的需求...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接