Как эффективно добавить столбец данных с вектором? - PullRequest
1 голос
/ 14 июня 2019

Работа с Юлией 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 Ответ

2 голосов
/ 14 июня 2019

Вы никогда не должны делать такие вещи, так как это приведет к тому, что многие функции из DataFrames.jl перестанут работать должным образом.На самом деле такой код скоро выдаст ошибку, см. https://github.com/JuliaData/DataFrames.jl/issues/1844, которая точно пытается исправить эту дыру в дизайне DataFrames.jl.

Что вам нужно сделать, это добавить объект, подобный фрейму данных, кDataFrame с использованием функции append! (это гарантирует, что результат имеет одинаковую длину столбцов) или с помощью push! для добавления одной строки в DataFrame.

Теперь причина нестабильности типа заключается в том, чтоDataFrame может содержать вектор любого типа (технически столбцы содержатся в Vector{AbstractVector}), поэтому во время компиляции невозможно определить, какой будет тип вектора под заданным именем.

EDIT

То, что вы просите, - это типичный сценарий, который 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 из NamedTuples).

Обратите внимание, что append! добавляет столбцы к DataFrame, используя сопоставление имен , поэтому имена столбцов должны быть согласованы между целевым и добавленным объектом.

Это отличается от push!, который такжепозволяет выдвинуть строку, в которой не указаны имена столбцов (в моем примере выше я показываю, что Tuple можно нажать).

...