首页 > 解决方案 > 在 Julia 中将一组数据帧转换为多维数组

问题描述

[一个朱莉娅菜鸟问题。]

假设我有一个数据帧向量,如下所示:

using DataFrames
A = DataFrame([8.1 9.2 7.5 6.6; 6.9 8.1 6.8 5.8])
B = DataFrame([9.0 2.1 5.2 5.3; 1.2 4.9 9.8 7.7])
dfs = [A, B]

当然,我实际上有dfs比这个 MWE 更多的数据框,但是它们都具有相同的维度,并且它们都只有数字列。

我想转换dfs成一个多维(这里是 2x4x2)数组arrarr[:, :, 1]等于 A,arr[:, :, 2]等于 B。我该如何执行这个转换?(当然,for循环可能会解决问题,但我想还有一种更优雅的方式来进行。)

谢谢!

标签: arraysdataframejulia

解决方案


我想

f1(dfs) = cat(Matrix.(dfs)..., dims=3)

是一个相当优雅的单线,但它分配临时。

从速度的角度来看,您可能可以使用以下单线轻松击败它

f2(dfs) = [ dfs[k][n,m] for n = 1:size(dfs[1],1), m = 1:size(dfs[1],2), k = 1:length(dfs) ]

话虽如此,如果您愿意更详细一点,您可能可以再次使用专门设计用于与DataFrame.

function f3(dfs)
    y = Array{Float64,3}(undef, size(dfs[1],1), size(dfs[1],2), length(dfs))
    for k = 1:length(dfs) ; for (n,col) in enumerate(eachcol(dfs[k]))
        y[:,n,k] = col
    end ; end
    return y
end

一般来说,如果你想要 Julia 的速度,循环通常是最好的方法。让我们快速比较一下这三种方法:

julia> using BenchmarkTools

julia> @btime f1($dfs);
  182.454 μs (132 allocations: 7.89 KiB)

julia> @btime f2($dfs);
  935.217 ns (21 allocations: 672 bytes)

julia> @btime f3($dfs);
  338.664 ns (11 allocations: 368 bytes)

所以比 .f3快 6 倍f1。您可以投入@inboundsf2进行f3进一步优化,尽管我怀疑它不会为您带来太多好处...

现在,公平地说,我只是假设一切都在Float64这里。但是,通过预先进行快速类型检查,您可以将其推广到任何类型(只要它都是一种类型 - 大概是因为您想要转换为单个数组)。


推荐阅读