Returning a NamedTuple fails with DataFrame combine

Viewed 27

Can someone tell me why using foo2, which returns a NamedTuple, with combine fails, but using foo, which returns a Tuple, is OK?

The error message I get is something about a Vector or Tuple is expected, but NamedTuple was given instead. I don't understand why returning a NamedTuple fails.

function foo(vals)
    (sum(vals), mean(vals))
end

function foo2(vals)
    (tot = sum(vals), avg = mean(vals))
end

df = DataFrame(:a => [1,1,2,2,3,3], :b => [10,20,30,40,50,60])
gdf = groupby(df, :a)

res = combine(gdf, :b => foo)    # OK
res2 = combine(gdf, :b => foo2)  # Not OK
1 Answers

The reason is that in DataFrames.jl NamedTuple is considered to have multiple columns. If you want to put it in a single column wrap the result in Ref:

julia> res2 = combine(gdf, :b => Ref∘foo2)
3×2 DataFrame
 Row │ a      b_Ref_foo2
     │ Int64  NamedTupl…
─────┼────────────────────────────────
   1 │     1  (tot = 30, avg = 15.0)
   2 │     2  (tot = 70, avg = 35.0)
   3 │     3  (tot = 110, avg = 55.0)

and if you want the result to be expanded into multiple columns set AsTable as target:

julia> res2 = combine(gdf, :b => foo2 => AsTable)
3×3 DataFrame
 Row │ a      tot    avg
     │ Int64  Int64  Float64
─────┼───────────────────────
   1 │     1     30     15.0
   2 │     2     70     35.0
   3 │     3    110     55.0
Related