# Subset a NamedTuple?

**URL:** <https://discourse.julialang.org/t/subset-a-namedtuple/127085>\
**Category:** General Usage\
**Created:** [March 18, 2025, 8:01am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085 "2025-03-18T08:01:44Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 8:01am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/1 "2025-03-18T08:01:44Z")

</div>

Is there a function to subset a NamedTuple? Like

```julia
nt = (a = 1, b = "hello", c = 3.14)
s = Base.subset(nt, :a, :c)

```

The above code, _ **which doesn’t work,** _ was generate by ChatGPT. It also generated another solution, which does work:

```julia
nt = (a = 1, b = "hello", c = 3.14)
keys = (:a, :c)
s = NamedTuple{keys}(nt)

```

So, was a function like `select` once provided? I like the former approach only because its intention is a bit clearer. Of course, I can live with the latter, or I can write my own `select` function . . .

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [March 18, 2025, 8:17am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/2 "2025-03-18T08:17:40Z")

</div>

```julia-repl
julia> nt = (a = 1, b = "hello", c = 3.14)
(a = 1, b = "hello", c = 3.14)

julia> nt[(:a, :c)]
(a = 1, c = 3.14)

```

I resorted to the documentation instead of ChatGPT:

> Accessing the value associated with a name in a named tuple can be done using  
> field access syntax, e.g. x.a, or using getindex, e.g. x[:a] or x[(:a, :b)].

---

<div class="post-metadata">

**Author:** ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)\
**Post date:** [March 18, 2025, 8:18am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/3 "2025-03-18T08:18:21Z")

</div>

Ah, the wonderful world of AI hallucinations. Just curious: what’s your use case?

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 8:36am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/4 "2025-03-18T08:36:46Z")

</div>

> [@barucden](#):
>
> I resorted to the documentation

Ah! Each time I ask a question here, I feel stupid. This had rarely happened before starting to use Julia. There is something about Julia that stumps Google and Bing.

Not in the present case, but it’s often hard to find the relevant information in the official documents. (In the present case, your comment made me locate the feature in the official documentation of `NamedTuple`. So, my bad, in the present case.)

So, I gave up. First Google and Bing. If it fails, ChatGPT. If it fails, I ask questions here. I should really search the official documents . . .

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 8:41am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/5 "2025-03-18T08:41:53Z")

</div>

> [@BdeKoning](#):
>
> Just curious: what’s your use case?

```julia
vars = read_data() # returns a large NamedTuple
subset = vars[(:a, :x, :q, :ii)] # Needs only a subset
func_with_optional_keyword_args(; subset...)

```

I don’t think this can be any simpler and clearer than this.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [March 18, 2025, 8:56am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/6 "2025-03-18T08:56:50Z")

</div>

It is admittedly hard to find information in the official docs! But it is also the most reliable source. I don’t use the web version very often, but I frequently look into the REPL’s help (in your case, `?NamedTuple`).

---

<div class="post-metadata">

**Author:** ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)\
**Post date:** [March 18, 2025, 9:32am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/7 "2025-03-18T09:32:45Z")

</div>

I see. If `func_with_optional_keyword_args` is yours, you could also adapt the signature to `func_with_optional_keyword_args(; a = :foo, x = :bar, q = :baz, ii = :qux, kwargs...)` and keep the whole named tuple.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 10:01am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/8 "2025-03-18T10:01:22Z")

</div>

> [@BdeKoning](#):
>
> If `func_with_optional_keyword_args` is yours, you could also adapt the signature to `func_with_optional_keyword_args(; a = :foo, x = :bar, q = :baz, ii = :qux, kwargs...)` and keep the whole named tuple.

That was my first thought: Accept the whole `NamedTuple` on the receiving function, but then my second thought was, why make it more complex than necessary? This was the starting point of this search of mine, in the first place.

Even though the data producing function `read_data()` and the data processing function `func_with_optional_keyword_args()` are in the same problem domain and share the names and meanings of the variables, I want to minimize the interface to _ **clarify the dependency.** _ I want to say, “this function requires this and that variables, not more.”

Otherwise, all functions end up appearing to depend on all variables out there:

```julia
(v1, v2, v3, . . . . ) = read_data()

function dothis()
  # use only v3, and v5
end
function dothat()
  # use only v1, and v12
end

```

This style “works” at first, but when you want to lift one of the functions you wrote some time ago for another program, it’s not immediately clear which variables the function depends on. So, it’s always desirable to minimize the function interface.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [March 18, 2025, 10:11am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/9 "2025-03-18T10:11:02Z")

</div>

I agree with your idea of minimizing the function interface. However, I am wondering: why is the first option preferred over the second in the following?

```julia
# Option 1
vars = read_data()
subset = vars[(:a, :x, :q, :ii)]
func_with_optional_keyword_args(; subset...)

# Option 2
vars = read_data()
func_with_optional_keyword_args(; vars.a, vars.x, vars.q, vars.ii)

```

You have to enumerate the arguments anyway, and the second option appears more explicit and transparent to me (it is not immediately apparent which arguments are set when calling `f(; subset...)`). Is it about brevity?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 18, 2025, 10:56am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/10 "2025-03-18T10:56:17Z")

</div>

> [@ryofurue](#):
>
> `Base.subset(nt, :a, :c)`

> [@BdeKoning](#):
>
> the wonderful world of AI hallucinations

Probably mixed it up with code using [DataFrames.subset](https://dataframes.juliadata.org/stable/lib/functions/#DataFrames.subset), possibly also confused by code with R’s [subset](https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/subset). Just a downside of a model trained on so much, it’s not very good at context, though prompts do help.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [March 18, 2025, 11:21am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/11 "2025-03-18T11:21:08Z")

</div>

I tried asking this on JuliaHub’s AskAI just to see if that’s a better option.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/b/1be49c6a69a9d6b4f582686587c4dee8c8f8c21c.png)

It recommended `select` from NamedTupleTools.jl, which at least seems to be [real](https://github.com/JeffreySarnoff/NamedTupleTools.jl?tab=readme-ov-file#select).

It did not mention the simple getindex option from the solution here though. I tried asking “Isn’t there a simpler way without external packages?” to see if it would arrive there. That somehow made it lose track of the context entirely, and talk in generic terms about using external packages.

So the answer by itself is somewhat better, but the UI is pretty atrocious (no history, no multiple chat threads, no editing even), and it seems to have a hard time keeping to the thread of the conversation, so I can’t really recommend this as a better chat interface. It’s an alternate to keep in mind and worth giving a try from time to time though.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 12:52pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/12 "2025-03-18T12:52:34Z")

</div>

> [@barucden](#):
>
> Is it about brevity?

That, and avoiding additional clutter. Reducing clutter leads to increased readability. My real code looks like this:

```julia
ful = get_data()
pij = ful.pij
ginv = 1/ful.gravit
sub = ful[(:dx, :dz, :bvf2e, :cee, :iocn, :kocn, :f0)]
args = (; sub..., ginv=ginv)
accuracy(view(pij,:,:,1); args...)

```

Before arriving at the present solution, my code was like

```julia
vars = get_data()
ginv = 1/vars.gravit
accuracy(view(vars.p2d, :,:,1) ; dx=vars.dx, dz=vars.dz, bvf2e=vars.bvf2e, c=vars.c
   ,f0=vars.f0, ginv=ginv, iocn=vars.iocn, kocn=vars.kocn)

```

See? The clutter of `vars.` and the repetition of the `x = vars.x` pattern reduce clarity in the latter case.

> [@barucden](#):
>
> the second option appears more explicit and transparent to me (it is not immediately apparent which arguments are set when calling `f(; subset...)`).

You exaggerate. The variables are listed one line or two before the function call:

```julia
args = vars[(:a, :c, :e, :f, . . .)]
func(; args...) # see the previous line! It's not far away.

```

vs

```julia
func(; a = vars.a, b = vars.b, c = vars.c, e = vars.e, f = vars.f)

```

Do you really think that the second is clearer than the first?

If you really prefers the second style, what about

```julia
func(; vars[(:a, :b, :c, :e, :f)]...)

```

? Explicit and brief. For my real code, I don’t take the 3rd approach because I need to calculate one argument (`ginv = 1/vars.gravit`) and separate out one positional argument (`pij = vars.pij`), but if I just pass a subset of the variables, I would use the 3rd style, or even

```julia
func(; read_data()[(:a, :b, :c, :e, :f)]...)

```

if I don’t need the full result from `read_data()` further.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [March 18, 2025, 1:10pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/13 "2025-03-18T13:10:09Z")

</div>

I don’t want to steal your topic — especially when you already got an answer to your question. I just want to note that it is not required to repeat the names of the keyword arguments; they can be derived from the variable names that you pass to the function. So I would indeed prefer

```julia
ful = get_data()
pij = ful.pij
ginv = 1/ful.gravit
accuracy(view(pij,:,:,1); 
         ful.dx, ful.dz, # I am assuming these two are related...
         ful.bvf2e,
         ful.cee,
         ful.iocn, ful.kocn, # ... as well as these two
         ful.f0, 
         ginv)

```

But of course — stick to _your_ preferred way! I was just curious.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [March 18, 2025, 1:39pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/14 "2025-03-18T13:39:45Z")

</div>

> [@ryofurue](#):
>
> ```julia
> (v1, v2, v3, . . . . ) = read_data()
> 
> function dothis()
> # use only v3, and v5
> end
> function dothat()
> # use only v1, and v12
> end
> 
> ```

I’d write:

```julia
function read_data()
...
  return (; v1, v2, etc...) # NamedTuple!
end

(;v1, v2, v3, . . . . ) = read_data()

function dothis(v3, v5)
  # do this
end
function dothat(v1, v12)
  # do that
end

```

or alternatively

```julia
function dothis(; v3, v5)
  # do this
end
function dothat(; v1, v12)
  # do that
end

```

or (what I actually usually do)

```julia
nt = read_data()

function dothis(; kwargs...)
  x = somewhat(v3)
  y = x + v5 # do something with v3 and v5
end

dothis(; nt...)

```

EDIT:  
I’ve copied from a post above as  
`(v1, v2, v3, . . . . ) = read_data()`

What I’d always do, and therefore overlook it’s something different here - I’d generally use `NamedTuple`s all the way through - I edited the example above correspondingly.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 18, 2025, 2:02pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/15 "2025-03-18T14:02:42Z")

</div>

> [@barucden](#):
>
> I just want to note that it is not required to repeat the names of the keyword arguments

I didn’t know that! Thank you!!!

But how is that possible?

```julia
function get_data()
  (a = "a", b = "b", c = "c", q = "q", r = "r", th = "th")
end

function func(; th = nothing, q = "", c = "empty", r = "hello")
  @show th, q, c, r
end

ful = get_data()
@show typeof(ful.q) # -> String
@show typeof(ful.r) # -> String
@show typeof("q") # -> String
@show typeof("r") # -> String
func(; ful.q, ful.r) # -> works!
func(; "q", "r") # -> fails.

```

The types of `ful.q` and `ful.r` are `String` and so are those of `"q"` and `"r"`. Yet, the first call works and the second call fails. I’m sure I’m missing something.

---

<div class="post-metadata">

**Author:** ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)\
**Post date:** [March 18, 2025, 2:14pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/16 "2025-03-18T14:14:57Z")

</div>

It’s not the type of the value assigned to a variable, it’s the variable’s name:

```julia
function f(;x=1)
end

x = 3
y = 3
f(;x) # works: `f` has a keyword argument called `x`
f(;y) # does not work: `f` does not have a keyword argument called `y`

```

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [March 18, 2025, 2:17pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/17 "2025-03-18T14:17:40Z")

</div>

If a keyword argument appears after a semicolon and without a `<keyword>=`, Julia will use the name of the variable as the keyword. I never knew, but apparently when there is a property access in the argument it will use the property name instead.

Both cases involve parser magic (maybe it’s not literally the parser but it’s pretty close) and cannot be derived from first principles regarding the rest of the language. This feature has only been around since roughly v1.7 so it’s also somewhat less known.

A related syntax is property destructuring:

```julia-repl
julia> (; a, b) = (; a=3, b=4, c=5)
(a = 3, b = 4, c = 5)

julia> a # `a` and `b` are now assigned
3

```

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [March 18, 2025, 5:25pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/18 "2025-03-18T17:25:56Z")

</div>

> [@ryofurue](#):
>
> I want to say, “this function requires this and that variables, not more.”

This is the solution I use.

```julia
"write docstring based on main method to be clear about inputs."
function f(x, y, z)
  # main function body
end
f(nt::NamedTuple) = f(nt.x, nt.y, nt.z)
```

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [March 19, 2025, 5:50am UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/19 "2025-03-19T05:50:59Z")

</div>

> This is the solution I use.

I believe you but I’m a bit surprised. By adding the interface `f(nt:NamedTuple)`, you miss an opportunity of the compiler checking argument mismatch:

```julia
# -- in one module
function f(; x = "hello", y = 3.14, z = nothing)
  @show x, y, z
end
f(nt::NamedTuple) = f(; nt.x, nt.y, nt.z)

function g(; x = "hello", y = 3.14, z = nothing)
  @show x, y, z
end

read_data() = (x = "x", z = "z", y = "y")

# -- in the main program
vars = read_data()

nt = (; vars..., yy = "yy")
#^^^ I thought the name was "yy" and I didn't know that vars included "y".

f(; x = "x", z = "z", y = "y") # works
f(; x = "x", z = "z", yy = "yy") # error
f(nt) # no error
g(; nt...) # error

```

The problem of the `f(nt:NamedTuple)` interface is that extra variables are silently ignored.

Coming back to my original question: It’s tedious to write `f(; x=vars.x, y=vars.y, . . .)` What’s a more succinct way to write it?

We have two possible designs:

1. Subset the original `NamedTuple` and send it to the function as `g(; subset...)`.
2. Write an extra interface to `f` to take all `NamedTuples` and send everything to the function as `f(nt)`.

I would argue that design 1 is superior. For design 2, you have to write an extra interface `f(nt:NamedTuple)` and accept some possibility of argument mismatch.

Design 1 doesn’t have any drawback once you know how to subset a given `NamedTuple`.

The above is a contrived, stupid example, but I do make argument mismatch error from time to time. I sometimes include the same variable twice in the argument list by mistake and if I misspell one of them, the mistake would go unnoticed if it’s in a `NamedTuple`. And I do use `NamedTuple` to pass a set of arguments to a function.

This is not a fictitious scenario. `Makie` the graphics library accepts any keyword arguments and doesn’t check for misspellings, silently ignoring those it doesn’t recognize. As a result, it sometimes takes a lot of time to find out your misspellings.

In other words, I want to say, “this function requires this and that variables, not more”, not only in documentations, but I want to tell that to the compiler.

---

<div class="post-metadata">

**Author:** ![Nathan\_Boyer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nathan_boyer/32/14825_2.png) [@Nathan\_Boyer](https://discourse.julialang.org/u/Nathan_Boyer)\
**Post date:** [March 19, 2025, 3:15pm UTC](https://discourse.julialang.org/t/subset-a-namedtuple/127085/20 "2025-03-19T15:15:30Z")

</div>

I accept that possibility for the simplicity, but I also don’t manually add to the `NamedTuple`. (I write `gather_<x>_input` functions which prompt the user for values and hardcode the keys.) If you want more robust control, I suggest writing function methods for custom [composite types](https://docs.julialang.org/en/v1/manual/types/#Composite-Types) instead of `NamedTuple` or `kwargs...`.

[Next page](https://discourse.julialang.org/t/subset-a-namedtuple/127085.md?page=2)
