ntrch
ntrch

Reputation: 96

An alternative for d3v4 "columns" (I have to use d3v3)

I need to implement the following code:

d3.csv("data.csv", function(d, i, columns) {
  for (i = 1, t = 0; i < columns.length; ++i) t += d[columns[i]] = +d[columns[i]];
  d.total = t;
  return d;
}, function(error, data) {
  if (error) throw error;
  var keys = data.columns.slice(1);
  ...

From: https://bl.ocks.org/mbostock/3886208

But, I have to use d3.js version 3. I found 'columns' in the d3 v4 API Reference:

The returned array also exposes a columns property containing the column names in input order (in contrast to Object.keys, whose iteration order is arbitrary).

For example: data.columns; // ["Year", "Make", "Model", "Length"]

But I'm struggling with coming up with something similar in version 3 to use for the keys variable, as shown at the last line of the quoted code:

var keys = data.columns.slice(1);

How can I use data to get the same d and keys without the "columns" property?

Upvotes: 2

Views: 577

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102194

Despite the fact that now you know the v3 version of that bl.ocks, it's woth mentioning that it's quite easy to create your own columns property, but with some drawbacks.

The source code in V4 that creates the columns property is this:

function inferColumns(rows) {
  var columnSet = Object.create(null),
      columns = [];

  rows.forEach(function(row) {
    for (var column in row) {
      if (!(column in columnSet)) {
        columns.push(columnSet[column] = column);
      }
    }
  });
  return columns;
}

We can make a (very) simplified version of it.

Here is a normal d3.csv code with D3 v3, I'm loading some CSV I found online:

d3.csv("https://www.ibm.com/support/knowledgecenter/SVU13_7.2.1/com.ibm.ismsaas.doc/reference/AssetsImportMinimumSample.csv?view=kc", function(data) {
  console.log(data)
})
<script src="https://d3js.org/d3.v3.min.js"></script>

We can create our columns getting the headers of that CSV with:

data.columns = d3.keys(data[0])

Here is the demo (look at your browser console, not the snippet's one):

d3.csv("https://www.ibm.com/support/knowledgecenter/SVU13_7.2.1/com.ibm.ismsaas.doc/reference/AssetsImportMinimumSample.csv?view=kc", function(data){
	data.columns = d3.keys(data[0])
  console.log(data)
})
<script src="https://d3js.org/d3.v3.min.js"></script>

But these are the drawbacks: first, this code is oversimplified: it doesn't take into account duplicated values, for instance. Second, It created the columns property after loading/parsing the file. Therefore, you cannot use columns in the row accessor function, because it doesn't exist at that point. Of corse you could create the columns property inside the row function, but that's not a very wise solution, because the row function is called for every row in the CSV, which can be hundreds or even thousands.

Upvotes: 2

Related Questions