How do I see the data in the documentation examples?

I’ve just started learning plot/d3, and am stuck at trying to reproduce the “stocks” examples as in the one at Plots | Observable Plot and at Normalize transform | Observable Plot.

I’ve downloaded a couple of stock data files in csv format Yahoo finance and have managed to load and plot them as follows:

async function drawGraph() {
  const goog = await d3.csv('GOOG.csv');
  const nflx = await d3.csv('NFLX.csv');
  const plot = Plot.plot({
    x: {
      transform: (d) => new Date(d),
      line: true,
    },
    y: {
      transform: (d) => +d,
      line: true,
      label: "Normalised Adj Close"
    },
    color: {
      legend: true
    },
    marginTop: 20,
    marginRight: 20,
    marginBottom: 30,
    marginLeft: 40,
    grid: true,
    marks: [
      Plot.line(goog, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "red"})),
      Plot.line(nflx, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "blue"}))
    ]
  });
  const div = document.querySelector("#myplot");
  div.append(plot);
}

drawGraph();

The snag I have is the color: { legend: true } entry seems to be getting completely ignored for reasons I don’t understand.

If I try to add text labels along the lines of the example in normalize, ie

    marks: [
      Plot.line(goog, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "red"})),
      Plot.line(nflx, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "blue"})),
      Plot.text(goog, Plot.selectLast(Plot.normalizeY({x: "Date", y: "Adj Close", text: "GOOG", textAnchor: "start", dx: 3}))),
      Plot.text(nflx, Plot.selectLast(Plot.normalizeY({x: "Date", y: "Adj Close", text: "NFLX", textAnchor: "start", dx: 3})))
    ]

also gets ignored.

I’m guessing the data used in the documentation examples has stuff my data doesn’t but I don’t know how to access that data to see what I’m doing wrong.

1 Like

The way you see the data depends a bit on which example you’re talking about. In both cases, though, the first step is to follow the link to fork the example. Your first example looks like so:

Notice where it says “Fork↗” just to the upper right. If you click on that, it will take you to a complete notebook that produces the plot.

Now, if you follow that notebook, you’ll find that the data appears in the variable appl but you might still be confused because that’s one of the auto-loaded “sample datasets”. Those are documented here:

You follow the fork link for the other example, you’ll find that the notebook contains several FileAttachments that are merged to form the dataset.

1 Like

To answer your other question, it’s because you’re using literal colors (stroke: "red" and stroke: "blue") rather than a color encoding, so you don’t have a color scale, and so Plot can’t produce a legend.

You can fix this by expressing the color in terms of data. The preferred way is to add a Symbol column in your data:

const [goog, nflx] = await Promises.all([
  d3.csv('GOOG.csv').then((data) => data.map((d) => ({...d, Symbol: "GOOG"}))),
  d3.csv('NFLX.csv').then((data) => data.map((d) => ({...d, Symbol: "NFLX"})))
]);
const data = [...goog, ...nflx];

Then you can say:

Plot.lineY(data, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "Symbol"}))

An alternative way would be to express the stroke as a function of data:

Plot.lineY(goog, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: () => "GOOG"}))

(I also switched to lineY here, which is preferred when x is time.)

2 Likes

To add to what Mark wrote, when viewing an example on Observable you can also reference the datasource variable in its own cell to inspect it:

1 Like

This text mark doesn’t render because your data doesn’t have a GOOG column. It would render if you add a Symbol column as described in my post above, or if you switch to text: () => "GOOG" to denote that the string "GOOG" represents a value than a column name.

1 Like

Many thanks for all the prompt and helpful replies.

My current version looks like so:

function add_symbol(stock, name) {
  stock.forEach((d) => {
    d.Symbol = name;
  });
}

async function drawGraph() {
  const goog = await d3.csv('GOOG.csv');
  const nflx = await d3.csv('NFLX.csv');
  add_symbol(goog, "GOOG");
  add_symbol(nflx, "NFLX");
  const plot = Plot.plot({
    x: {
      transform: (d) => new Date(d),
      line: true
    },
    y: {
      transform: (d) => +d,
      line: true,
      label: "Normalised Adj Close"
    },
    color: {
      legend: true,
    },
    marginTop: 20,
    marginRight: 20,
    marginBottom: 30,
    marginLeft: 40,
    grid: true,
    marks: [
      Plot.lineY(goog, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "Symbol"})),
      Plot.lineY(nflx, Plot.normalizeY({x: "Date", y: "Adj Close", stroke: "Symbol"})),
      Plot.text(goog, Plot.selectLast(Plot.normalizeY({x: "Date", y: "Adj Close", text: "Symbol", textAnchor: "start", dx: 3}))),
      Plot.text(nflx, Plot.selectLast(Plot.normalizeY({x: "Date", y: "Adj Close", text: "Symbol", textAnchor: "start", dx: 3})))
    ]
  });
  const div = document.querySelector("#myplot");
  div.append(plot);
}

drawGraph();

I’m still a bit confused about how legends and scales work. My next challenge is to try use my own selected color for each stock graph, which I guess is in the documentation which I’m in the process of working through.

1 Like

If there’s something we can clarify here, please let us know!

1 Like