Search code examples
juliaargument-unpackingjuliadb

Is it possible to unpack a dictionary of parameters in a JuliaDB push!() function?


I recognize that JuliaDB may still be a bit rough around the edges, but I was wondering if it's possible to do something like this:

push!(rows(mse_table), table_params...) # add row

Instead of something like this:

push!(rows(mse_table), (samples=i,fixed=0.4, silverman=0.3, abramson=0.2, ervkde=0.1)) # add row


For the sake of reproducible code, the following creates a lovely little table with JuliaDB:

using JuliaDB

colnames = [:samples, :fixed, :silverman, :abramson, :ervkde]
primary_key = [:samples]
coltypes = [Int[], Float64[],Float64[],Float64[],Float64[]]
sample_sizes = [100,200,300]

mse_table = table(coltypes..., names=colnames, pkey=primary_key) # initialize empty table

for i in sample_sizes
    example_values = (i, 0.4, 0.3, 0.2, 0.1)
    table_params = [(col=>val) for (col,val) in zip(colnames, example_values)]

    # My question is, is there a way to do something like this:
#     push!(rows(mse_table), table_params...) # add row

#     Instead of this:
    push!(rows(mse_table), (samples=i,fixed=0.4, silverman=0.3, abramson=0.2, ervkde=0.1)) # add row

    mse_table = table(mse_table, pkey = primary_key, copy = false) # sort rows by primary key
end
mse_table = table(unique(mse_table), pkey=primary_key) # remove duplicate rows


Thanks in advance.


Solution

  • You can build a NamedTuple from an array of Pairs in the following way:

    julia> arr = [:a=>1, :b=>2]
    2-element Array{Pair{Symbol,Int64},1}:
     :a => 1
     :b => 2
    
    julia> nt = (; arr...)
    (a = 1, b = 2)
    

    Therefore, the following example should work:

    julia> using JuliaDB
    julia> colnames = [:samples, :fixed, :silverman, :abramson, :ervkde];
    julia> primary_key = [:samples];
    julia> coltypes = [Int[], Float64[],Float64[],Float64[],Float64[]];
    julia> mse_table = table(coltypes..., names=colnames, pkey=primary_key);
    
    julia> example_values = (1, 0.4, 0.3, 0.2, 0.1);
    
           # more compact than the comprehension you used;
           # maybe not more readable...
    julia> row = map(Pair, colnames, example_values)
    5-element Array{Pair{Symbol,B} where B,1}:
       :samples => 1
         :fixed => 0.4
     :silverman => 0.3
      :abramson => 0.2
        :ervkde => 0.1
    
           # (; row...) builds a NamedTuple
    julia> push!(rows(mse_table), (; row...));
    julia> mse_table
    Table with 1 rows, 5 columns:
    samples  fixed  silverman  abramson  ervkde
    ───────────────────────────────────────────
    1.0      0.4    0.3        0.2       0.1
    


    NB: I don't use JuliaDB at all, so this way of doing things might not be idiomatic!