如何有效地将数据框列附加向量?

时间:2019-06-14 14:22:43

标签: dataframe append julia

使用Julia 1.1:

以下最少的代码可以正常工作并满足我的要求:

 function test()
    df = DataFrame(NbAlternative = Int[], NbMonteCarlo = Int[], Similarity = Float64[])
    append!(df.NbAlternative, ones(Int, 5))
    df
 end

将向量附加到df的一列。注意:在我的整个代码中,我添加的Vector{Int}比返回的ones'更复杂。

但是,@code_warntype test()确实返回:

%8  = invoke DataFrames.getindex(%7::DataFrame, :NbAlternative::Symbol)::AbstractArray{T,1} where T

我想这意味着什么,效率不高。我无法理解这个@code_warntype错误的含义。更笼统地说,我如何理解@code_warntype返回的错误并加以解决,这对我来说是一个反复出现的问题。

编辑:@BogumiłKamiński的答案 那么如何执行以下代码?

for na in arr_nb_alternative
    @show na
    for mt in arr_nb_montecarlo
        println("...$mt")
        append!(df.NbAlternative, ones(Int, nb_simulations)*na)
        append!(df.NbMonteCarlo, ones(Int, nb_simulations)*mt)
        append!(df.Similarity, compare_smaa(na, nb_criteria, nb_simulations, mt))
    end
end

compare_smaa返回一个nb_simulations长度向量。

1 个答案:

答案 0 :(得分:2)

您永远不要做这样的事情,因为它会导致DataFrames.jl中的许多功能停止正常工作。实际上,这样的代码很快就会引发错误,请参见https://github.com/JuliaData/DataFrames.jl/issues/1844,它正试图修补DataFrames.jl设计中的此漏洞。

您应该做的是使用DataFrame函数(这样可以保证结果具有一致的列长)或使用append!将一个类似数据框架的对象附加到push!单行到DataFrame

现在,类型不稳定的原因是DataFrame可以容纳任何类型的向量(技术上列在Vector{AbstractVector}中),因此无法在编译时确定给定名称下的向量类型。

编辑

您要的是一个典型的场景,DataFrames.jl很好地支持了这个场景,并且我几乎每天都这样做(因为我做了很多模拟)。正如我已指出的那样-您可以使用push!append!。使用push!添加一次模拟运行(这不是您的情况,但我添加它是因为它也很常见):

for na in arr_nb_alternative
    @show na
    for mt in arr_nb_montecarlo
        println("...$mt")
        for i in 1:nb_simulations
            # here you have to make sure that compare_smaa returns a scalar
            # if it is passed 1 in nb_simulations
            push!(df, (na, mt, compare_smaa(na, nb_criteria, 1, mt)))
        end
    end
end

这就是您使用append!的方式:

for na in arr_nb_alternative
    @show na
    for mt in arr_nb_montecarlo
        println("...$mt")
        # here you have to make sure that compare_smaa returns a vector
        append!(df, (NbAlternative=ones(Int, nb_simulations)*na,
                     NbMonteCarlo=ones(Int, nb_simulations)*mt,
                     Similarity=compare_smaa(na, nb_criteria, nb_simulations, mt)))
    end
end

请注意,我在此处附加了NamedTuple。如前所述,您可以通过这种方式附加一个DataFrame或任何类似数据框架的对象。 “类似数据框架的对象”的意思是一类广泛的东西-通常,您可以传递给DataFrame构造函数的任何东西(例如,它也可以是Vector的{​​{1}})

请注意,NamedTuples使用名称匹配将列添加到append!中,因此目标名称和附加对象之间的列名称必须一致。

这与DataFrame不同,它也允许推送未指定列名的行(在上面的示例中,我显示了可以推送push!的行)。