Convert NamedTuple with matrix to DataFrame

Hello,

I was wondering if there is a simple way to convert a NamedTuple with a mix of vectors and matrices, such as,

np = (x = [1 1; 1 2; 2 1; 2 2], y = [1,2,3,4])

to a DataFrame, such as

df = DataFrame(x1 = [1,1,2,2], x2=[1,2,1,2], y=[1,2,3,4])

4×3 DataFrame
 Row │ x1     x2     y     
     │ Int64  Int64  Int64 
─────┼─────────────────────
   1 │     1      1      1
   2 │     1      2      2
   3 │     2      1      3
   4 │     2      2      4

Thank you.

FWIW:

DataFrame(reduce(vcat, eachcol(x) for x in np), [:x1, :x2, :y])
1 Like
hcat(DataFrame(np.x,:auto),DataFrame(;np.y))
DataFrame(hcat(np.x,np.y),:auto)
DataFrame(hcat(np...),:auto)
2 Likes
DataFrame(["$k$i" => c for (k,v) in pairs(np) for (i, c) in pairs(eachcol(v))])
2 Likes

Thank you everyone for the suggestions. I think the one by sijo is the closest to what I am aiming for. I think the only drawback is the extra “1” added to y. I’ll see if I can find a way to add numbers to columns of matrices.

You could tweak it further:

DataFrame([(k == :x ? "$k$i" : "$k") => c  for (k,v) in pairs(np) for (i, c) in pairs(eachcol(v))])

I assume you have a more general situation like the following.
You could adapt the script like this

julia> np = (x = [1 1; 1 2; 2 1; 2 2],z = [1 1; 1 2; 2 1; 2 2], y = [1,2,3,4])
(x = [1 1; 1 2; 2 1; 2 2], z = [1 1; 1 2; 2 1; 2 2], y = [1, 2, 3, 4])

julia> DataFrame([v isa Matrix ? "$k$i" => c : "$k" => c for (k,v) in pairs(np) for (i, c) in pairs(eachcol(v))])
4×5 DataFrame
 Row │ x1     x2     z1     z2     y     
     │ Int64  Int64  Int64  Int64  Int64
─────┼───────────────────────────────────
   1 │     1      1      1      1      1
   2 │     1      2      1      2      2
   3 │     2      1      2      1      3
   4 │     2      2      2      2      4
julia> DataFrame(["$k" => c  for (k,v) in pairs(np) for c in eachcol(v)],makeunique=true)    
4×5 DataFrame
 Row │ x      x_1    z      z_1    y     
     │ Int64  Int64  Int64  Int64  Int64
─────┼───────────────────────────────────
   1 │     1      1      1      1      1
   2 │     1      2      1      2      2
   3 │     2      1      2      1      3
   4 │     2      2      2      2      4

2 Likes

Another method to tweak rafael’s answer which doesn’t add 1 to y:

DataFrame(["$k"*"$i"^(v!=c)=>c for (k,v) in pairs(np) for
  (i,c) in pairs(eachcol(v))])
3 Likes