spyrostheodoridis
spyrostheodoridis

Reputation: 518

d3.tsv/d3.csv columns in accessor (row) function

Consider the following tsv file:

Code    k1  k2
pf_1    0.2 0.3
pf_2    0.3 0.7
pf_3    0.2 0.4
pf_4    0.1 0.6
pf_5    0.8 0.9

I 've been trying to understand how the following code works but haven't found a clear answer:

d3.tsv("test.tsv") 
    .row(function(d, i, columns){ d.total = columns.length; return d;})
    .get(function(d){ console.log(d);});

The specific questions I have are the following:

Upvotes: 2

Views: 1481

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

What is the underlying parse function that maps the third (columns) argument to the column names in the accessor (row) function?

The accessor function, also known as the row conversion function, is a function invoked for each row, and it takes 3 arguments (which will answer your second question further down):

  • The first argument is the row
  • The second argument is the index, starting at zero
  • The third argument is the column names array

This third argument is interesting, and it was introduced in D3 v4.x. I believe that it answers your first question:

When you load a CSV (or a TSV), d3.csv (or d3.tsv) creates an array property with the headers, named columns (take care with loops like a for...in loop, because it will include that property) . In the case of your example, it is:

columns: ["Code", "k1", "k2"]

And it lead us to your second question:

Why do I need the row iterator (i) argument in the accessor function?

You don't. The thing is that this piece of code uses the third argument, which is the columns property, and for being able to use the third argument we have to supply the two arguments that come before it, even if we don't use them:

.row(function(d, i, columns){ d.total = columns.length; return d;}) 
//3rd argument---------^

There is a convention in JavaScript, not very famous I reckon, that an unused parameter should be named as an underscore (_). In that case, this function would be:

.row(function(d, _, columns){ d.total = columns.length; return d;}) 
//not used-------^

So, what that code does is getting the value of columns.length, which is 3, and creating a new property to each object:

d.total = columns.length; return d;

So, the objects will end up like this:

{Code: "pf_1", k1: "0.2", k2: "0.3", total: 3}

With the new property total.

Upvotes: 5

Related Questions