This should do it
julia> gd = groupby(df1, "NAME");
julia> max_cols = mapreduce(d -> length(unique(d.CAT)), max, gd);
julia> combine(gd) do sdf
cs = unique(sdf.CAT)
cs_out = [i <= length(cs) ? cs[i] : "" for i in 1:max_rows]
colnames_out = [Symbol("CAT", i) for i in 1:max_cols]
NamedTuple{Tuple(colnames_out)}(Tuple(cs_out))
end
3×4 DataFrame
Row │ NAME CAT1 CAT2 CAT3
│ String String String String
─────┼────────────────────────────────
1 │ A1 FIN NF INF
2 │ A2 UTL GT
3 │ A3 CP MP