1

I'm working on an application where datasets have programmatically generated names and are frequently created and destroyed by users. I want to graph these datasets within the application using D3.js.

My datasets are stored like this:

Wavelength Transducer Output 1 Transducer Output 2 Transducer Output 3
1 19 21 23
3 23 20 21
5 33 23 19
7 33 24 45
etc.. etc.. etc.. etc..

Where wavelength should be mapped along the x axis, and magnitude mapped along the y axis, with an individual line for each set of magnitudes.

I'm struggling to get my head around how one should pass such data into D3.js. Each tutorial I read uses different data formats and different code. I have read the documentation, but it hasn't helped me much in learning how to format my data for D3 either.

What's the correct way to map these datasets onto a graph from within a script? At the moment I'm trying to use d3.csvParse(data), but am unsure where to go from there. I suspect I may be formatting my data awkwardly but am not sure.

  • What type of graph are you looking to create with this dataset? – Alexander Nied Mar 08 '22 at 03:18
  • @AlexanderNied a line plot with several groups, like [this example here](https://www.d3-graph-gallery.com/graph/line_several_group.html) – Tadgh Wagstaff Mar 08 '22 at 03:20
  • I suggest you to show how exactly your CSV is (just the header plus a few rows), so we can start from there. Is it just like that table? – Gerardo Furtado Mar 08 '22 at 03:36
  • @GerardoFurtado The data is currently formatted exactly like that table, although I can format the data however you would recommend if there are more convenient formats; I'm brand new to all of this. :) – Tadgh Wagstaff Mar 08 '22 at 03:58
  • _"Where wavelength should be mapped along the x axis, and magnitude mapped along the y axis, with an individual line for each set of magnitudes."_ So am I correct in saying that, for what you want to do, and how D3 reads data by row, the fundamental problem you have is that you need each _column_ to be read in, rather than each _row_? If that's a true statement, then at a quick glance D3 has utilities to manage this-- see [`d3.zip` & `d3.transpose`](https://observablehq.com/@d3/d3-transpose). – Alexander Nied Mar 08 '22 at 04:31
  • @AlexanderNied Thanks, I legitimately hadn't realized that that was the problem but it sounds correct. Essentially this data measures output of a broadband transducer, where the output varies by wavelength. I need to plot the response of each transducer over the band that I'm interested in. My confusion stems from how I should present that data to D3; convention for datasets like these is to store them in columns, but I don't know how to make that click with D3. I can store the data internally in a different format, but for now I'll try using those utilities. Thanks for your help :) – Tadgh Wagstaff Mar 08 '22 at 14:45

1 Answers1

2

Writing up a quick answer to this just incase anyone else gets stuck where I did. Essentially I completely misunderstood how you're supposed to present data to in d3.

Here's a useful guide to understanding d3 data handling

Here's a useful guide on how to use that data once you have it structured correctly

Once I realised that I needed to create an array which represented every point I want drawn things got a lot easier. I created an object with three properties that described a single data point.

Each object has a wavelength, magnitude, and a name.

wavelength is the datapoint's position on the x axis, magnitude is its position on the y axis, and name allows me to differentiate between the different datasets.

let array = [
{name: "dataset 1", wavelength: 2, magnitude: 20}
{name: "dataset 1", wavelength: 3, magnitude: 22}
{name: "dataset 1", wavelength: 4, magnitude: 19}
{name: "dataset 2", wavelength: 2, magnitude: 14} //and so on...
]

From there I could map that onto my graph with

svg.append("path")
.data(array)
.attr("d", d3.line()
    .x(function(d) {return x(d.wavelength)})
    .y(function(d) {return y(d.magnitude)})
    .z(function(d) {return z(d.name)});

You can also group the data by name using d3.group() and iterate through that through your data manually, drawing each line individually

Thanks @Alexander Nied and @Gerardo Furtado for nudging me back on track!