# Deconstruct NamedTupleColumn with Prefix

**URL:** https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297
**Category:** Data
**Tags:** dataframes
**Created:** [August 1, 2025, 5:07pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297 "2025-08-01T17:07:40Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![mreichMPI-BGC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mreichmpi-bgc/32/43775_2.png) [@mreichMPI-BGC](https://discourse.julialang.org/u/mreichMPI-BGC)
#### Post date: [August 1, 2025, 5:07pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/1 "2025-08-01T17:07:40Z")

</div>

Similar to this one: [Transform! to destructure NamedTuple into columns](https://discourse.julialang.org/t/transform-to-destructure-namedtuple-into-columns/74991)

I’d like to do the same, but be able to programmatically prefix the "child"columns with the “parent” prefix.

That is in the linked MWE, I would like to get column names x\_a and x\_b (automatically)

Something like

```julia-auto
nms = df.x[1] |> keys .|> string
rename!(df, (nms .=> "x" .* nms)...)

```

works but feels cumbersome. Can it be done directly in the transform statement?

Thanks!

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [August 1, 2025, 7:00pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/2 "2025-08-01T19:00:54Z")

</div>

Nothing super easy in DataFrames.jl for this, unfortunately. You could do

```julia-auto
julia> function add_prefix(nt, pre)
           nms = Symbol.(pre, "_", propertynames(nt))
           vals = values(nt)
           NamedTuple{nms}(vals)
       end
add_prefix (generic function with 1 method)

julia> df = DataFrame(x = rand(2), y =[(a=1,b=2),(a=3,b=5)])
2×2 DataFrame
 Row │ x y
     │ Float64 NamedTup…
─────┼──────────────────────────
   1 │ 0.485175 (a = 1, b = 2)
   2 │ 0.822109 (a = 3, b = 5)

julia> transform(df, :y => ByRow(t -> add_prefix(t, "y")) => AsTable)
2×4 DataFrame
 Row │ x y y_a y_b
     │ Float64 NamedTup… Int64 Int64
─────┼────────────────────────────────────────
   1 │ 0.485175 (a = 1, b = 2) 1 2
   2 │ 0.822109 (a = 3, b = 5) 3 5

```

But that doesn’t give you the name “y” automatically. If you really want access to column names inside the `fun` of `src => fun => dest` you could do `AsTable(src) => ...` but that’s probably more trouble than its worth.

---

<div class="post-metadata">

### Author: ![drizk1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drizk1/32/208422_2.png) [@drizk1](https://discourse.julialang.org/u/drizk1)
#### Post date: [August 5, 2025, 2:37pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/3 "2025-08-05T14:37:28Z")

</div>

Another option would be [`@unnest_wider`](https://tidierorg.github.io/TidierData.jl/latest/examples/generated/UserGuide/nesting/#unnest_wider) from TidierData. It will automatically prefix the column names, but it will drop the original column which might add some performance benefit

```julia-auto
julia> using TidierData; df = DataFrame(x = rand(2), y =[(a=1,b=2),(a=3,b=5)]);

julia> @time transform(df, :y => ByRow(t -> add_prefix(t, "y")) => AsTable)
  0.031335 seconds (67.12 k allocations: 3.632 MiB, 98.90% compilation time)
2×4 DataFrame
 Row │ x y y_a y_b   
     │ Float64 NamedTup… Int64 Int64 
─────┼────────────────────────────────────────
   1 │ 0.478783 (a = 1, b = 2) 1 2
   2 │ 0.741308 (a = 3, b = 5) 3 5

julia> @time @unnest_wider(df, y)
  0.000086 seconds (96 allocations: 4.539 KiB)
2×3 DataFrame
 Row │ x y_a y_b   
     │ Float64 Int64 Int64 
─────┼────────────────────────
   1 │ 0.478783 1 2
   2 │ 0.741308 3 5

```

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [August 5, 2025, 2:50pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/4 "2025-08-05T14:50:22Z")

</div>

It’s worth noting that if the `add_prefix` method is in a function, there is no performance different (it’s all due to compilation of the anonymous function)

```julia-auto
julia> using DataFrames

julia> df = DataFrame(x = rand(2), y =[(a=1,b=2),(a=3,b=5)]);

julia> function add_prefix(nt, pre)
                  nms = Symbol.(pre, "_", propertynames(nt))
                  vals = values(nt)
                  NamedTuple{nms}(vals)
              end
add_prefix (generic function with 1 method)

julia> foo(df) = transform(df, :y => ByRow(t -> add_prefix(t, "y")) => AsTable)
foo (generic function with 1 method)

julia> @time foo(df); # Warmup
  0.032263 seconds (140.54 k allocations: 7.444 MiB, 99.42% compilation time)

julia> @time foo(df); # After warmup
  0.000157 seconds (134 allocations: 5.594 KiB)

```

So it’s not really “performance” per-se, as much as less lag when interacting at the REPL or running a script in global scope (which may be common).

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [August 5, 2025, 8:12pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/5 "2025-08-05T20:12:42Z")

</div>

If I’m not mistaken, this appears to be a more efficient approach:

```julia-auto
hcat(df, DataFrame(df.y, [Symbol(:x_, k) for k in keys(first(df.y))]))

```

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [August 5, 2025, 9:17pm UTC](https://discourse.julialang.org/t/deconstruct-namedtuplecolumn-with-prefix/131297/6 "2025-08-05T21:17:23Z")

</div>

Yeah my implementation is not very good. If OP really cares about performance it would be best to not re-calculate the names of the tuples every time.

```julia-auto
julia> function add_prefix(nt, pre)
           nt_long = Tables.columntable(nt)
           nms = Symbol.(pre, "_", propertynames(nt_long))
           NamedTuple{nms}(values(nt_long))
       end;

julia> df = DataFrame(x = rand(2), y =[(a=1,b=2),(a=3,b=5)]);

julia> @transform! df $AsTable = add_prefix(:y, "y")
2×4 DataFrame
 Row │ x y y_a y_b   
     │ Float64 NamedTup… Int64 Int64 
─────┼─────────────────────────────────────────
   1 │ 0.0859943 (a = 1, b = 2) 1 2
   2 │ 0.743904 (a = 3, b = 5) 3 5

```

This is definitely less useable than the `TidierData` version, of course. I can think of an improvement in DataFramesMeta.
