# Assigning plots to variables

**URL:** <https://talk.observablehq.com/t/assigning-plots-to-variables/8192>\
**Category:** Help\
**Created:** [August 14, 2023, 6:02pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192 "2023-08-14T18:02:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![boshek](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@boshek](https://talk.observablehq.com/u/boshek)\
**Post date:** [August 14, 2023, 6:02pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/1 "2023-08-14T18:02:45Z")

</div>

This likely betrays my Javascript inexperience but I am wondering what the best approach is to conditionally return certain plots? My made up example is to say "produce one type of plot when one value is selected in `Inputs.select` and produce another if more than one are selected. I don’t quite understand how one can assign a plot to a variable and use it later. Right now I am doing something like this:

```js
{
if (islands.length === 1) {
     return Plot.plot({
        grid: true,
        inset: 10,
        color: {legend: true},
        marks: [
          Plot.frame(),
          Plot.dot(pen_sub, {x: "bill_length_mm", y: "bill_depth_mm", stroke: "green"})
        ]
      });
} else if (islands.length > 1) {
    return Plot.plot({
        grid: true,
        inset: 10,
        color: {legend: true},
        marks: [
          Plot.frame(),
          Plot.dot(pen_sub, {x: "bill_length_mm", y: "bill_depth_mm", stroke: "species"})
        ]
      });
}

```

However I am wondering if I can make that a little nicer by assigning the two plots to variables and then just reference those variables? I have a notebook here: [penguins data / Sam Albers | Observable](https://observablehq.com/d/ceabffedd591a3fd)

I’ve just tried assigning them to a variable but I get an “undefined” output. For example I am not certain quite why this doesn’t work:

```js
length_one_plot = Plot.plot({
        grid: true,
        inset: 10,
        color: {legend: true},
        marks: [
          Plot.frame(),
          Plot.dot(pen_sub, {x: "bill_length_mm", y: "bill_depth_mm", stroke: "green"})
        ]
      })

length_gt_one_plot = Plot.plot({
        grid: true,
        inset: 10,
        color: {legend: true},
        marks: [
          Plot.frame(),
          Plot.dot(pen_sub, {x: "bill_length_mm", y: "bill_depth_mm", stroke: "species"})
        ]
      });

{
  if (islands.length === 1) {
    return length_one_plot;
  } else if (islands.length > 1) {
    return length_gt_one_plot;
  }
}

```

TIA.

---

<div class="post-metadata">

**Author:** ![jwoLondon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jwolondon/32/259_2.png) [@jwoLondon](https://talk.observablehq.com/u/jwoLondon)\
**Post date:** [August 14, 2023, 6:31pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/2 "2023-08-14T18:31:37Z")

</div>

Because the difference in your two versions of the plot are minor, in this case I’d be inclined to use the [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator) to specify the two different colour encodings. This keeps the specification nice and compact:

```auto
Plot.plot({
  grid: true,
  inset: 10,
  color: { legend: true },
  marks: [
    Plot.frame(),
    Plot.dot(pen_sub, {
      x: "bill_length_mm",
      y: "bill_depth_mm",
      stroke: islands.length === 1 ? "green" : "species"
    })
  ]
})

```

---

<div class="post-metadata">

**Author:** ![boshek](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@boshek](https://talk.observablehq.com/u/boshek)\
**Post date:** [August 14, 2023, 6:37pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/3 "2023-08-14T18:37:28Z")

</div>

Thanks for this! Yeah I can see how in my example that would work great. But for my actual use case, I’d really like to understand how to properly assign these because the plots are very different.

---

<div class="post-metadata">

**Author:** ![mythmon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mythmon/32/8504_2.png) [@mythmon](https://talk.observablehq.com/u/mythmon)\
**Post date:** [August 14, 2023, 6:42pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/4 "2023-08-14T18:42:27Z")

</div>

Can you share an example of what you tried already where the notebook isn’t working how you want?

---

<div class="post-metadata">

**Author:** ![jwoLondon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jwolondon/32/259_2.png) [@jwoLondon](https://talk.observablehq.com/u/jwoLondon)\
**Post date:** [August 14, 2023, 6:44pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/5 "2023-08-14T18:44:29Z")

</div>

If you need to store plot specifications without actually displaying them at the point you specifying them there are a number of options. But one simple one is to recognise that `Plot.plot()` is just a function that takes a JavaScript object with the plot specification as a parameter. So you could store that parameter object and then Plot it when needed.

For example:

```auto
mySpec1 = ({
  grid: true,
  inset: 10,
  color: { legend: true },
  marks: [
    Plot.frame(),
    Plot.dot(pen_sub, {
      x: "bill_length_mm",
      y: "bill_depth_mm",
      stroke: "green"
    })
  ]
})

```

And then when needed:

```auto
Plot.plot(mySpec1)

```

You can store these specs just as you would any other values, for example in arrays, objects, Maps etc.

---

<div class="post-metadata">

**Author:** ![boshek](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@boshek](https://talk.observablehq.com/u/boshek)\
**Post date:** [August 14, 2023, 6:49pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/6 "2023-08-14T18:49:16Z")

</div>

I’ve updated the notebook and the question to reflect that. Thanks for the prod.

---

<div class="post-metadata">

**Author:** ![boshek](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@boshek](https://talk.observablehq.com/u/boshek)\
**Post date:** [August 14, 2023, 6:53pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/7 "2023-08-14T18:53:33Z")

</div>

Oh wow. This really helped click something into place for me. This certainly [works](https://observablehq.com/d/ceabffedd591a3fd#cell-128) but I am curious where I might read more about the other options.

---

<div class="post-metadata">

**Author:** ![jwoLondon](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/jwolondon/32/259_2.png) [@jwoLondon](https://talk.observablehq.com/u/jwoLondon)\
**Post date:** [August 14, 2023, 7:18pm UTC](https://talk.observablehq.com/t/assigning-plots-to-variables/8192/8 "2023-08-14T19:18:17Z")

</div>

I think the approach to use depends on what you are intending to achieve.

Assigning the full specification objects to variables gives you lots of flexibility in that there need be no relation between each specification. But it can result in a ‘bad code smell’ in that there may be lots of repetition in the specs, especially as they get longer.

My instinct is to try to minimise code repetition and isolate the conditional elements of a spec. That is what led my suggestion for the ternary operator.

If the conditional dependencies are more complex than binary alternatives, you could create the specification as a function where you parameterise the bits you need to. For example:

```auto
function myCustomSpec(clr) {
  return {
    grid: true,
    inset: 10,
    color: { legend: true },
    marks: [
      Plot.frame(),
      Plot.dot(pen_sub, {
        x: "bill_length_mm",
        y: "bill_depth_mm",
        stroke: clr // "species" or "green" or any other colour provided by parameter.
      })
    ]
  };
}

```

But if you have a function, you many not need to store the spec separately from the call to Plot.plot() because it is only invoked at the point you call the function:

```auto
function myCustomPlot(clr) {
  return Plot.plot({
    grid: true,
    inset: 10,
    color: { legend: true },
    marks: [
      Plot.frame(),
      Plot.dot(pen_sub, {
        x: "bill_length_mm",
        y: "bill_depth_mm",
        stroke: clr // "species" or "green" or any other colour provided here.
      })
    ]
  });
}

```

```auto
myCustomPlot("green")

```

It’s also worth remembering that many of the values in a Plot specification can be functions themselves (using the compact [arrow function notation](https://javascript.info/arrow-functions-basics)) which allows you to customise different parts of a specification. The Plot documentation has plenty of examples that use arrow functions (look for `(d) =>...`) to help you build an understanding of how and when they can be useful.

Finally, something I find useful for more complex plots is not to store entire specifications as variables, but just each of the marks. This allows you to attach meaningful names to them, making reading the code easier, and helps if you need to selectively add or remove marks. This is the approach I used in this [wheat and wages exercise](https://observablehq.com/@jwolondon/wheat-and-wages):

```auto
Plot.plot({
  width: w,
  height: h,
  margin: margin,
  style: `background:${bgClr}; font-family: ${fnt.script};`,
  x: xAxis,
  marks: [
    barsAndArea,
    yAxes,
    grid,
    monarchs,
    century,
    titlePanel,
    annotation
  ].flat()
})

```
