Restructuring a csv file with d3js

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












In my code below I have restructured the following csv file from something like this:



date,type
2017-01,E
2017-01,E
2017-01,E
2017-01,U


To this:



date: "2017-01", E: 3, U: 1


Using d3.nest() with a rollup method.



The only thing is that I'm mapping out the type values somewhat manually like this:



var lineData = nestData.map(function(d) 
return date: d.key, E: d.values[0].value, U: d.values[1].value;
);


always expecting the types to be in order. I do this by simply sorting the data by type and then re-sort by date again.



What I basically want to know is if there's a better way of achieving this or if there's a step or two that I can omit from the code making it more efficient.



Here's all the code:






var csvData = 
`date,type
2017-01,E
2017-01,E
2017-01,E
2017-01,U
2017-01,U
2017-02,E
2017-02,E
2017-02,U
2017-02,U
2017-02,U
2017-03,U
2017-03,U
2017-03,E
2017-03,E
2017-03,E
2017-03,E`;

var durations = 0;

var parseTime = d3.timeParse("%Y-%m");

var margin = top: 25, right: 25, bottom: 25, left: 25,
width = 420 - margin.left - margin.right,
height = 185 - margin.top - margin.bottom;

var g = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);

var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%B"))
.ticks(3);

var yAxis = d3.axisLeft(y).ticks(4);

var line = d3.line()
.curve(d3.curveCardinal)
.x(function(d) return x(d.date); )
.y(function(d) return y(d.lines); );

g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")");

g.append("g")
.attr("class", "axis axis--y");

var data = d3.csvParse(csvData, function(d)
d.date = d.date;
d.type = d.type
return d;
).sort((a, b) => a.type - b.type)

var nestData = d3.nest()
.key(d => d.date)
.key(d => d.type)
.rollup(leaves => leaves.length)
.entries(data);

console.log("Nested: ", nestData)

var lineData = nestData.map(function(d)
return date: d.key, E: d.values[0].value, U: d.values[1].value;
);

lineData.forEach(function(d)
d.date = parseTime(d.date);
)

lineData.sort((a, b) => a.date - b.date)

console.log("Mapped: ", lineData)

parsed(lineData);

function parsed(dataTest)

var keys = ["E","U"]

var newData = keys.map(function(id)
return
id: id,
values: dataTest.map(function(d)
return date: d.date, lines: d[id];
)
;
);

console.log("Mapped w/key: ", newData)

z.domain(newData.map(function(c) return c.id; ));

var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

y.domain([0, max]).nice();

x.domain(d3.extent(dataTest, d => d.date));

g.selectAll(".axis.axis--y").transition()
.duration(durations)
.call(yAxis);

g.selectAll(".axis.axis--x").transition()
.duration(durations)
.call(xAxis);

var lineValues = g.selectAll(".lineValues")
.data(newData);

lineValues = lineValues
.enter()
.append("path")
.attr("class", "line lineValues")
.style("stroke", function(d) return z(d.id); )
.merge(lineValues);

lineValues.transition()
.duration(durations)
.attr("d", function(d) return line(d.values) )


.line 
fill: none;
stroke: steelblue;
stroke-width: 1.5px;

<html>
<head>
<meta charset ="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>

<style type="text/css">

.line
fill: none;
stroke: steelblue;
stroke-width: 1.5px;


</style>
</head>

<body>

<div id="chart"></div>

<script>
</script>

</body>
</html>









share|improve this question

























    up vote
    2
    down vote

    favorite












    In my code below I have restructured the following csv file from something like this:



    date,type
    2017-01,E
    2017-01,E
    2017-01,E
    2017-01,U


    To this:



    date: "2017-01", E: 3, U: 1


    Using d3.nest() with a rollup method.



    The only thing is that I'm mapping out the type values somewhat manually like this:



    var lineData = nestData.map(function(d) 
    return date: d.key, E: d.values[0].value, U: d.values[1].value;
    );


    always expecting the types to be in order. I do this by simply sorting the data by type and then re-sort by date again.



    What I basically want to know is if there's a better way of achieving this or if there's a step or two that I can omit from the code making it more efficient.



    Here's all the code:






    var csvData = 
    `date,type
    2017-01,E
    2017-01,E
    2017-01,E
    2017-01,U
    2017-01,U
    2017-02,E
    2017-02,E
    2017-02,U
    2017-02,U
    2017-02,U
    2017-03,U
    2017-03,U
    2017-03,E
    2017-03,E
    2017-03,E
    2017-03,E`;

    var durations = 0;

    var parseTime = d3.timeParse("%Y-%m");

    var margin = top: 25, right: 25, bottom: 25, left: 25,
    width = 420 - margin.left - margin.right,
    height = 185 - margin.top - margin.bottom;

    var g = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform",
    "translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scaleTime().range([0, width]),
    y = d3.scaleLinear().range([height, 0]),
    z = d3.scaleOrdinal(d3.schemeCategory10);

    var xAxis = d3.axisBottom(x)
    .tickFormat(d3.timeFormat("%B"))
    .ticks(3);

    var yAxis = d3.axisLeft(y).ticks(4);

    var line = d3.line()
    .curve(d3.curveCardinal)
    .x(function(d) return x(d.date); )
    .y(function(d) return y(d.lines); );

    g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")");

    g.append("g")
    .attr("class", "axis axis--y");

    var data = d3.csvParse(csvData, function(d)
    d.date = d.date;
    d.type = d.type
    return d;
    ).sort((a, b) => a.type - b.type)

    var nestData = d3.nest()
    .key(d => d.date)
    .key(d => d.type)
    .rollup(leaves => leaves.length)
    .entries(data);

    console.log("Nested: ", nestData)

    var lineData = nestData.map(function(d)
    return date: d.key, E: d.values[0].value, U: d.values[1].value;
    );

    lineData.forEach(function(d)
    d.date = parseTime(d.date);
    )

    lineData.sort((a, b) => a.date - b.date)

    console.log("Mapped: ", lineData)

    parsed(lineData);

    function parsed(dataTest)

    var keys = ["E","U"]

    var newData = keys.map(function(id)
    return
    id: id,
    values: dataTest.map(function(d)
    return date: d.date, lines: d[id];
    )
    ;
    );

    console.log("Mapped w/key: ", newData)

    z.domain(newData.map(function(c) return c.id; ));

    var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

    y.domain([0, max]).nice();

    x.domain(d3.extent(dataTest, d => d.date));

    g.selectAll(".axis.axis--y").transition()
    .duration(durations)
    .call(yAxis);

    g.selectAll(".axis.axis--x").transition()
    .duration(durations)
    .call(xAxis);

    var lineValues = g.selectAll(".lineValues")
    .data(newData);

    lineValues = lineValues
    .enter()
    .append("path")
    .attr("class", "line lineValues")
    .style("stroke", function(d) return z(d.id); )
    .merge(lineValues);

    lineValues.transition()
    .duration(durations)
    .attr("d", function(d) return line(d.values) )


    .line 
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;

    <html>
    <head>
    <meta charset ="utf-8">
    <script src="https://d3js.org/d3.v4.min.js"></script>

    <style type="text/css">

    .line
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;


    </style>
    </head>

    <body>

    <div id="chart"></div>

    <script>
    </script>

    </body>
    </html>









    share|improve this question





















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      In my code below I have restructured the following csv file from something like this:



      date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U


      To this:



      date: "2017-01", E: 3, U: 1


      Using d3.nest() with a rollup method.



      The only thing is that I'm mapping out the type values somewhat manually like this:



      var lineData = nestData.map(function(d) 
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );


      always expecting the types to be in order. I do this by simply sorting the data by type and then re-sort by date again.



      What I basically want to know is if there's a better way of achieving this or if there's a step or two that I can omit from the code making it more efficient.



      Here's all the code:






      var csvData = 
      `date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U
      2017-01,U
      2017-02,E
      2017-02,E
      2017-02,U
      2017-02,U
      2017-02,U
      2017-03,U
      2017-03,U
      2017-03,E
      2017-03,E
      2017-03,E
      2017-03,E`;

      var durations = 0;

      var parseTime = d3.timeParse("%Y-%m");

      var margin = top: 25, right: 25, bottom: 25, left: 25,
      width = 420 - margin.left - margin.right,
      height = 185 - margin.top - margin.bottom;

      var g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
      "translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      z = d3.scaleOrdinal(d3.schemeCategory10);

      var xAxis = d3.axisBottom(x)
      .tickFormat(d3.timeFormat("%B"))
      .ticks(3);

      var yAxis = d3.axisLeft(y).ticks(4);

      var line = d3.line()
      .curve(d3.curveCardinal)
      .x(function(d) return x(d.date); )
      .y(function(d) return y(d.lines); );

      g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      var data = d3.csvParse(csvData, function(d)
      d.date = d.date;
      d.type = d.type
      return d;
      ).sort((a, b) => a.type - b.type)

      var nestData = d3.nest()
      .key(d => d.date)
      .key(d => d.type)
      .rollup(leaves => leaves.length)
      .entries(data);

      console.log("Nested: ", nestData)

      var lineData = nestData.map(function(d)
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );

      lineData.forEach(function(d)
      d.date = parseTime(d.date);
      )

      lineData.sort((a, b) => a.date - b.date)

      console.log("Mapped: ", lineData)

      parsed(lineData);

      function parsed(dataTest)

      var keys = ["E","U"]

      var newData = keys.map(function(id)
      return
      id: id,
      values: dataTest.map(function(d)
      return date: d.date, lines: d[id];
      )
      ;
      );

      console.log("Mapped w/key: ", newData)

      z.domain(newData.map(function(c) return c.id; ));

      var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

      y.domain([0, max]).nice();

      x.domain(d3.extent(dataTest, d => d.date));

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var lineValues = g.selectAll(".lineValues")
      .data(newData);

      lineValues = lineValues
      .enter()
      .append("path")
      .attr("class", "line lineValues")
      .style("stroke", function(d) return z(d.id); )
      .merge(lineValues);

      lineValues.transition()
      .duration(durations)
      .attr("d", function(d) return line(d.values) )


      .line 
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;

      <html>
      <head>
      <meta charset ="utf-8">
      <script src="https://d3js.org/d3.v4.min.js"></script>

      <style type="text/css">

      .line
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;


      </style>
      </head>

      <body>

      <div id="chart"></div>

      <script>
      </script>

      </body>
      </html>









      share|improve this question











      In my code below I have restructured the following csv file from something like this:



      date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U


      To this:



      date: "2017-01", E: 3, U: 1


      Using d3.nest() with a rollup method.



      The only thing is that I'm mapping out the type values somewhat manually like this:



      var lineData = nestData.map(function(d) 
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );


      always expecting the types to be in order. I do this by simply sorting the data by type and then re-sort by date again.



      What I basically want to know is if there's a better way of achieving this or if there's a step or two that I can omit from the code making it more efficient.



      Here's all the code:






      var csvData = 
      `date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U
      2017-01,U
      2017-02,E
      2017-02,E
      2017-02,U
      2017-02,U
      2017-02,U
      2017-03,U
      2017-03,U
      2017-03,E
      2017-03,E
      2017-03,E
      2017-03,E`;

      var durations = 0;

      var parseTime = d3.timeParse("%Y-%m");

      var margin = top: 25, right: 25, bottom: 25, left: 25,
      width = 420 - margin.left - margin.right,
      height = 185 - margin.top - margin.bottom;

      var g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
      "translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      z = d3.scaleOrdinal(d3.schemeCategory10);

      var xAxis = d3.axisBottom(x)
      .tickFormat(d3.timeFormat("%B"))
      .ticks(3);

      var yAxis = d3.axisLeft(y).ticks(4);

      var line = d3.line()
      .curve(d3.curveCardinal)
      .x(function(d) return x(d.date); )
      .y(function(d) return y(d.lines); );

      g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      var data = d3.csvParse(csvData, function(d)
      d.date = d.date;
      d.type = d.type
      return d;
      ).sort((a, b) => a.type - b.type)

      var nestData = d3.nest()
      .key(d => d.date)
      .key(d => d.type)
      .rollup(leaves => leaves.length)
      .entries(data);

      console.log("Nested: ", nestData)

      var lineData = nestData.map(function(d)
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );

      lineData.forEach(function(d)
      d.date = parseTime(d.date);
      )

      lineData.sort((a, b) => a.date - b.date)

      console.log("Mapped: ", lineData)

      parsed(lineData);

      function parsed(dataTest)

      var keys = ["E","U"]

      var newData = keys.map(function(id)
      return
      id: id,
      values: dataTest.map(function(d)
      return date: d.date, lines: d[id];
      )
      ;
      );

      console.log("Mapped w/key: ", newData)

      z.domain(newData.map(function(c) return c.id; ));

      var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

      y.domain([0, max]).nice();

      x.domain(d3.extent(dataTest, d => d.date));

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var lineValues = g.selectAll(".lineValues")
      .data(newData);

      lineValues = lineValues
      .enter()
      .append("path")
      .attr("class", "line lineValues")
      .style("stroke", function(d) return z(d.id); )
      .merge(lineValues);

      lineValues.transition()
      .duration(durations)
      .attr("d", function(d) return line(d.values) )


      .line 
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;

      <html>
      <head>
      <meta charset ="utf-8">
      <script src="https://d3js.org/d3.v4.min.js"></script>

      <style type="text/css">

      .line
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;


      </style>
      </head>

      <body>

      <div id="chart"></div>

      <script>
      </script>

      </body>
      </html>








      var csvData = 
      `date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U
      2017-01,U
      2017-02,E
      2017-02,E
      2017-02,U
      2017-02,U
      2017-02,U
      2017-03,U
      2017-03,U
      2017-03,E
      2017-03,E
      2017-03,E
      2017-03,E`;

      var durations = 0;

      var parseTime = d3.timeParse("%Y-%m");

      var margin = top: 25, right: 25, bottom: 25, left: 25,
      width = 420 - margin.left - margin.right,
      height = 185 - margin.top - margin.bottom;

      var g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
      "translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      z = d3.scaleOrdinal(d3.schemeCategory10);

      var xAxis = d3.axisBottom(x)
      .tickFormat(d3.timeFormat("%B"))
      .ticks(3);

      var yAxis = d3.axisLeft(y).ticks(4);

      var line = d3.line()
      .curve(d3.curveCardinal)
      .x(function(d) return x(d.date); )
      .y(function(d) return y(d.lines); );

      g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      var data = d3.csvParse(csvData, function(d)
      d.date = d.date;
      d.type = d.type
      return d;
      ).sort((a, b) => a.type - b.type)

      var nestData = d3.nest()
      .key(d => d.date)
      .key(d => d.type)
      .rollup(leaves => leaves.length)
      .entries(data);

      console.log("Nested: ", nestData)

      var lineData = nestData.map(function(d)
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );

      lineData.forEach(function(d)
      d.date = parseTime(d.date);
      )

      lineData.sort((a, b) => a.date - b.date)

      console.log("Mapped: ", lineData)

      parsed(lineData);

      function parsed(dataTest)

      var keys = ["E","U"]

      var newData = keys.map(function(id)
      return
      id: id,
      values: dataTest.map(function(d)
      return date: d.date, lines: d[id];
      )
      ;
      );

      console.log("Mapped w/key: ", newData)

      z.domain(newData.map(function(c) return c.id; ));

      var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

      y.domain([0, max]).nice();

      x.domain(d3.extent(dataTest, d => d.date));

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var lineValues = g.selectAll(".lineValues")
      .data(newData);

      lineValues = lineValues
      .enter()
      .append("path")
      .attr("class", "line lineValues")
      .style("stroke", function(d) return z(d.id); )
      .merge(lineValues);

      lineValues.transition()
      .duration(durations)
      .attr("d", function(d) return line(d.values) )


      .line 
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;

      <html>
      <head>
      <meta charset ="utf-8">
      <script src="https://d3js.org/d3.v4.min.js"></script>

      <style type="text/css">

      .line
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;


      </style>
      </head>

      <body>

      <div id="chart"></div>

      <script>
      </script>

      </body>
      </html>





      var csvData = 
      `date,type
      2017-01,E
      2017-01,E
      2017-01,E
      2017-01,U
      2017-01,U
      2017-02,E
      2017-02,E
      2017-02,U
      2017-02,U
      2017-02,U
      2017-03,U
      2017-03,U
      2017-03,E
      2017-03,E
      2017-03,E
      2017-03,E`;

      var durations = 0;

      var parseTime = d3.timeParse("%Y-%m");

      var margin = top: 25, right: 25, bottom: 25, left: 25,
      width = 420 - margin.left - margin.right,
      height = 185 - margin.top - margin.bottom;

      var g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform",
      "translate(" + margin.left + "," + margin.top + ")");

      var x = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      z = d3.scaleOrdinal(d3.schemeCategory10);

      var xAxis = d3.axisBottom(x)
      .tickFormat(d3.timeFormat("%B"))
      .ticks(3);

      var yAxis = d3.axisLeft(y).ticks(4);

      var line = d3.line()
      .curve(d3.curveCardinal)
      .x(function(d) return x(d.date); )
      .y(function(d) return y(d.lines); );

      g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")");

      g.append("g")
      .attr("class", "axis axis--y");

      var data = d3.csvParse(csvData, function(d)
      d.date = d.date;
      d.type = d.type
      return d;
      ).sort((a, b) => a.type - b.type)

      var nestData = d3.nest()
      .key(d => d.date)
      .key(d => d.type)
      .rollup(leaves => leaves.length)
      .entries(data);

      console.log("Nested: ", nestData)

      var lineData = nestData.map(function(d)
      return date: d.key, E: d.values[0].value, U: d.values[1].value;
      );

      lineData.forEach(function(d)
      d.date = parseTime(d.date);
      )

      lineData.sort((a, b) => a.date - b.date)

      console.log("Mapped: ", lineData)

      parsed(lineData);

      function parsed(dataTest)

      var keys = ["E","U"]

      var newData = keys.map(function(id)
      return
      id: id,
      values: dataTest.map(function(d)
      return date: d.date, lines: d[id];
      )
      ;
      );

      console.log("Mapped w/key: ", newData)

      z.domain(newData.map(function(c) return c.id; ));

      var max = d3.max(dataTest, d => d3.max([d.E, d.U]));

      y.domain([0, max]).nice();

      x.domain(d3.extent(dataTest, d => d.date));

      g.selectAll(".axis.axis--y").transition()
      .duration(durations)
      .call(yAxis);

      g.selectAll(".axis.axis--x").transition()
      .duration(durations)
      .call(xAxis);

      var lineValues = g.selectAll(".lineValues")
      .data(newData);

      lineValues = lineValues
      .enter()
      .append("path")
      .attr("class", "line lineValues")
      .style("stroke", function(d) return z(d.id); )
      .merge(lineValues);

      lineValues.transition()
      .duration(durations)
      .attr("d", function(d) return line(d.values) )


      .line 
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;

      <html>
      <head>
      <meta charset ="utf-8">
      <script src="https://d3js.org/d3.v4.min.js"></script>

      <style type="text/css">

      .line
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;


      </style>
      </head>

      <body>

      <div id="chart"></div>

      <script>
      </script>

      </body>
      </html>








      share|improve this question










      share|improve this question




      share|improve this question









      asked Feb 7 at 15:28









      Robert Andersson

      1667




      1667




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          First of all: drop the row function, which is the anonymous function as the second argument of csvParse...



          var data = d3.csvParse(csvData, function(d) 
          d.date = d.date;
          d.type = d.type
          return d;
          )


          ... because you are not changing anything!



          So, it can be just:



          var data = d3.csvParse(csvData);


          Back to your question:



          Indeed, you don't need to reference the array by the indices, which forces you to sort the data array and then to sort the resulting array... that's not only confusing and error-prone, but also very computer-intensive for the browser: sorting big arrays of objects can take quite some time. It's a good idea avoiding sorting, specially because, as we'll see, you don't need it.



          There is a way to omit that step, making it automatic. Better than that, you can make the whole thing automatic!



          In my proposed solution, you don't even need to set the keys, as you do right now...



          var keys = ["E","U"];


          You can easily get all the unique type values:



          var keys = [...new Set(data.map(function(d) 
          return d.type
          ))];


          And then, creating your lineData:



          var lineData = nestData.map(function(d) 
          var obj = ;
          obj.date = d.key;
          keys.forEach(function(e)
          obj[e] = d.values.find(function(f)
          return f.key === e
          ).value
          );
          return obj;
          );


          The above code will work for any number of different types you have, and since you already have the dates in the chronological order, you don't need any sort.



          This, in short, is what the function does:




          1. For each map interaction we create a new object:



            var obj = ;



          2. We set the key/value pair for the dates, since there is always a date:



            obj.date = d.key;



          3. Then, for each value in the keys array, we find the respective value in the values array:



            keys.forEach(function(e) 
            obj[e] = d.values.find(function(f)
            return f.key === e
            ).value
            );



          4. Finally, we return the object:



            return obj;


          Here is a demo, using only the relevant parts in your code:






          var csvData = `date,type
          2017-01,E
          2017-01,E
          2017-01,E
          2017-01,U
          2017-01,U
          2017-02,E
          2017-02,E
          2017-02,U
          2017-02,U
          2017-02,U
          2017-03,U
          2017-03,U
          2017-03,E
          2017-03,E
          2017-03,E
          2017-03,E`;

          var parseTime = d3.timeParse("%Y-%m");

          var data = d3.csvParse(csvData);

          var keys = [...new Set(data.map(function(d)
          return d.type
          ))];

          var nestData = d3.nest()
          .key(d => d.date)
          .key(d => d.type)
          .rollup(leaves => leaves.length)
          .entries(data);

          var lineData = nestData.map(function(d)
          var obj = ;
          obj.date = d.key;
          keys.forEach(function(e)
          obj[e] = d.values.find(function(f)
          return f.key === e
          ).value
          );
          return obj;
          );

          lineData.forEach(function(d)
          d.date = parseTime(d.date);
          )

          console.log("Nested: ", nestData)

          console.log("Mapped: ", lineData)

          <script src="https://d3js.org/d3.v4.min.js"></script>
          <svg></svg>





          Now, using this code, you can automatically create the adequate lineData array regardless the number and the order of the type properties in your data array.






          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187018%2frestructuring-a-csv-file-with-d3js%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            First of all: drop the row function, which is the anonymous function as the second argument of csvParse...



            var data = d3.csvParse(csvData, function(d) 
            d.date = d.date;
            d.type = d.type
            return d;
            )


            ... because you are not changing anything!



            So, it can be just:



            var data = d3.csvParse(csvData);


            Back to your question:



            Indeed, you don't need to reference the array by the indices, which forces you to sort the data array and then to sort the resulting array... that's not only confusing and error-prone, but also very computer-intensive for the browser: sorting big arrays of objects can take quite some time. It's a good idea avoiding sorting, specially because, as we'll see, you don't need it.



            There is a way to omit that step, making it automatic. Better than that, you can make the whole thing automatic!



            In my proposed solution, you don't even need to set the keys, as you do right now...



            var keys = ["E","U"];


            You can easily get all the unique type values:



            var keys = [...new Set(data.map(function(d) 
            return d.type
            ))];


            And then, creating your lineData:



            var lineData = nestData.map(function(d) 
            var obj = ;
            obj.date = d.key;
            keys.forEach(function(e)
            obj[e] = d.values.find(function(f)
            return f.key === e
            ).value
            );
            return obj;
            );


            The above code will work for any number of different types you have, and since you already have the dates in the chronological order, you don't need any sort.



            This, in short, is what the function does:




            1. For each map interaction we create a new object:



              var obj = ;



            2. We set the key/value pair for the dates, since there is always a date:



              obj.date = d.key;



            3. Then, for each value in the keys array, we find the respective value in the values array:



              keys.forEach(function(e) 
              obj[e] = d.values.find(function(f)
              return f.key === e
              ).value
              );



            4. Finally, we return the object:



              return obj;


            Here is a demo, using only the relevant parts in your code:






            var csvData = `date,type
            2017-01,E
            2017-01,E
            2017-01,E
            2017-01,U
            2017-01,U
            2017-02,E
            2017-02,E
            2017-02,U
            2017-02,U
            2017-02,U
            2017-03,U
            2017-03,U
            2017-03,E
            2017-03,E
            2017-03,E
            2017-03,E`;

            var parseTime = d3.timeParse("%Y-%m");

            var data = d3.csvParse(csvData);

            var keys = [...new Set(data.map(function(d)
            return d.type
            ))];

            var nestData = d3.nest()
            .key(d => d.date)
            .key(d => d.type)
            .rollup(leaves => leaves.length)
            .entries(data);

            var lineData = nestData.map(function(d)
            var obj = ;
            obj.date = d.key;
            keys.forEach(function(e)
            obj[e] = d.values.find(function(f)
            return f.key === e
            ).value
            );
            return obj;
            );

            lineData.forEach(function(d)
            d.date = parseTime(d.date);
            )

            console.log("Nested: ", nestData)

            console.log("Mapped: ", lineData)

            <script src="https://d3js.org/d3.v4.min.js"></script>
            <svg></svg>





            Now, using this code, you can automatically create the adequate lineData array regardless the number and the order of the type properties in your data array.






            share|improve this answer



























              up vote
              1
              down vote



              accepted










              First of all: drop the row function, which is the anonymous function as the second argument of csvParse...



              var data = d3.csvParse(csvData, function(d) 
              d.date = d.date;
              d.type = d.type
              return d;
              )


              ... because you are not changing anything!



              So, it can be just:



              var data = d3.csvParse(csvData);


              Back to your question:



              Indeed, you don't need to reference the array by the indices, which forces you to sort the data array and then to sort the resulting array... that's not only confusing and error-prone, but also very computer-intensive for the browser: sorting big arrays of objects can take quite some time. It's a good idea avoiding sorting, specially because, as we'll see, you don't need it.



              There is a way to omit that step, making it automatic. Better than that, you can make the whole thing automatic!



              In my proposed solution, you don't even need to set the keys, as you do right now...



              var keys = ["E","U"];


              You can easily get all the unique type values:



              var keys = [...new Set(data.map(function(d) 
              return d.type
              ))];


              And then, creating your lineData:



              var lineData = nestData.map(function(d) 
              var obj = ;
              obj.date = d.key;
              keys.forEach(function(e)
              obj[e] = d.values.find(function(f)
              return f.key === e
              ).value
              );
              return obj;
              );


              The above code will work for any number of different types you have, and since you already have the dates in the chronological order, you don't need any sort.



              This, in short, is what the function does:




              1. For each map interaction we create a new object:



                var obj = ;



              2. We set the key/value pair for the dates, since there is always a date:



                obj.date = d.key;



              3. Then, for each value in the keys array, we find the respective value in the values array:



                keys.forEach(function(e) 
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );



              4. Finally, we return the object:



                return obj;


              Here is a demo, using only the relevant parts in your code:






              var csvData = `date,type
              2017-01,E
              2017-01,E
              2017-01,E
              2017-01,U
              2017-01,U
              2017-02,E
              2017-02,E
              2017-02,U
              2017-02,U
              2017-02,U
              2017-03,U
              2017-03,U
              2017-03,E
              2017-03,E
              2017-03,E
              2017-03,E`;

              var parseTime = d3.timeParse("%Y-%m");

              var data = d3.csvParse(csvData);

              var keys = [...new Set(data.map(function(d)
              return d.type
              ))];

              var nestData = d3.nest()
              .key(d => d.date)
              .key(d => d.type)
              .rollup(leaves => leaves.length)
              .entries(data);

              var lineData = nestData.map(function(d)
              var obj = ;
              obj.date = d.key;
              keys.forEach(function(e)
              obj[e] = d.values.find(function(f)
              return f.key === e
              ).value
              );
              return obj;
              );

              lineData.forEach(function(d)
              d.date = parseTime(d.date);
              )

              console.log("Nested: ", nestData)

              console.log("Mapped: ", lineData)

              <script src="https://d3js.org/d3.v4.min.js"></script>
              <svg></svg>





              Now, using this code, you can automatically create the adequate lineData array regardless the number and the order of the type properties in your data array.






              share|improve this answer

























                up vote
                1
                down vote



                accepted







                up vote
                1
                down vote



                accepted






                First of all: drop the row function, which is the anonymous function as the second argument of csvParse...



                var data = d3.csvParse(csvData, function(d) 
                d.date = d.date;
                d.type = d.type
                return d;
                )


                ... because you are not changing anything!



                So, it can be just:



                var data = d3.csvParse(csvData);


                Back to your question:



                Indeed, you don't need to reference the array by the indices, which forces you to sort the data array and then to sort the resulting array... that's not only confusing and error-prone, but also very computer-intensive for the browser: sorting big arrays of objects can take quite some time. It's a good idea avoiding sorting, specially because, as we'll see, you don't need it.



                There is a way to omit that step, making it automatic. Better than that, you can make the whole thing automatic!



                In my proposed solution, you don't even need to set the keys, as you do right now...



                var keys = ["E","U"];


                You can easily get all the unique type values:



                var keys = [...new Set(data.map(function(d) 
                return d.type
                ))];


                And then, creating your lineData:



                var lineData = nestData.map(function(d) 
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );


                The above code will work for any number of different types you have, and since you already have the dates in the chronological order, you don't need any sort.



                This, in short, is what the function does:




                1. For each map interaction we create a new object:



                  var obj = ;



                2. We set the key/value pair for the dates, since there is always a date:



                  obj.date = d.key;



                3. Then, for each value in the keys array, we find the respective value in the values array:



                  keys.forEach(function(e) 
                  obj[e] = d.values.find(function(f)
                  return f.key === e
                  ).value
                  );



                4. Finally, we return the object:



                  return obj;


                Here is a demo, using only the relevant parts in your code:






                var csvData = `date,type
                2017-01,E
                2017-01,E
                2017-01,E
                2017-01,U
                2017-01,U
                2017-02,E
                2017-02,E
                2017-02,U
                2017-02,U
                2017-02,U
                2017-03,U
                2017-03,U
                2017-03,E
                2017-03,E
                2017-03,E
                2017-03,E`;

                var parseTime = d3.timeParse("%Y-%m");

                var data = d3.csvParse(csvData);

                var keys = [...new Set(data.map(function(d)
                return d.type
                ))];

                var nestData = d3.nest()
                .key(d => d.date)
                .key(d => d.type)
                .rollup(leaves => leaves.length)
                .entries(data);

                var lineData = nestData.map(function(d)
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );

                lineData.forEach(function(d)
                d.date = parseTime(d.date);
                )

                console.log("Nested: ", nestData)

                console.log("Mapped: ", lineData)

                <script src="https://d3js.org/d3.v4.min.js"></script>
                <svg></svg>





                Now, using this code, you can automatically create the adequate lineData array regardless the number and the order of the type properties in your data array.






                share|improve this answer















                First of all: drop the row function, which is the anonymous function as the second argument of csvParse...



                var data = d3.csvParse(csvData, function(d) 
                d.date = d.date;
                d.type = d.type
                return d;
                )


                ... because you are not changing anything!



                So, it can be just:



                var data = d3.csvParse(csvData);


                Back to your question:



                Indeed, you don't need to reference the array by the indices, which forces you to sort the data array and then to sort the resulting array... that's not only confusing and error-prone, but also very computer-intensive for the browser: sorting big arrays of objects can take quite some time. It's a good idea avoiding sorting, specially because, as we'll see, you don't need it.



                There is a way to omit that step, making it automatic. Better than that, you can make the whole thing automatic!



                In my proposed solution, you don't even need to set the keys, as you do right now...



                var keys = ["E","U"];


                You can easily get all the unique type values:



                var keys = [...new Set(data.map(function(d) 
                return d.type
                ))];


                And then, creating your lineData:



                var lineData = nestData.map(function(d) 
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );


                The above code will work for any number of different types you have, and since you already have the dates in the chronological order, you don't need any sort.



                This, in short, is what the function does:




                1. For each map interaction we create a new object:



                  var obj = ;



                2. We set the key/value pair for the dates, since there is always a date:



                  obj.date = d.key;



                3. Then, for each value in the keys array, we find the respective value in the values array:



                  keys.forEach(function(e) 
                  obj[e] = d.values.find(function(f)
                  return f.key === e
                  ).value
                  );



                4. Finally, we return the object:



                  return obj;


                Here is a demo, using only the relevant parts in your code:






                var csvData = `date,type
                2017-01,E
                2017-01,E
                2017-01,E
                2017-01,U
                2017-01,U
                2017-02,E
                2017-02,E
                2017-02,U
                2017-02,U
                2017-02,U
                2017-03,U
                2017-03,U
                2017-03,E
                2017-03,E
                2017-03,E
                2017-03,E`;

                var parseTime = d3.timeParse("%Y-%m");

                var data = d3.csvParse(csvData);

                var keys = [...new Set(data.map(function(d)
                return d.type
                ))];

                var nestData = d3.nest()
                .key(d => d.date)
                .key(d => d.type)
                .rollup(leaves => leaves.length)
                .entries(data);

                var lineData = nestData.map(function(d)
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );

                lineData.forEach(function(d)
                d.date = parseTime(d.date);
                )

                console.log("Nested: ", nestData)

                console.log("Mapped: ", lineData)

                <script src="https://d3js.org/d3.v4.min.js"></script>
                <svg></svg>





                Now, using this code, you can automatically create the adequate lineData array regardless the number and the order of the type properties in your data array.






                var csvData = `date,type
                2017-01,E
                2017-01,E
                2017-01,E
                2017-01,U
                2017-01,U
                2017-02,E
                2017-02,E
                2017-02,U
                2017-02,U
                2017-02,U
                2017-03,U
                2017-03,U
                2017-03,E
                2017-03,E
                2017-03,E
                2017-03,E`;

                var parseTime = d3.timeParse("%Y-%m");

                var data = d3.csvParse(csvData);

                var keys = [...new Set(data.map(function(d)
                return d.type
                ))];

                var nestData = d3.nest()
                .key(d => d.date)
                .key(d => d.type)
                .rollup(leaves => leaves.length)
                .entries(data);

                var lineData = nestData.map(function(d)
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );

                lineData.forEach(function(d)
                d.date = parseTime(d.date);
                )

                console.log("Nested: ", nestData)

                console.log("Mapped: ", lineData)

                <script src="https://d3js.org/d3.v4.min.js"></script>
                <svg></svg>





                var csvData = `date,type
                2017-01,E
                2017-01,E
                2017-01,E
                2017-01,U
                2017-01,U
                2017-02,E
                2017-02,E
                2017-02,U
                2017-02,U
                2017-02,U
                2017-03,U
                2017-03,U
                2017-03,E
                2017-03,E
                2017-03,E
                2017-03,E`;

                var parseTime = d3.timeParse("%Y-%m");

                var data = d3.csvParse(csvData);

                var keys = [...new Set(data.map(function(d)
                return d.type
                ))];

                var nestData = d3.nest()
                .key(d => d.date)
                .key(d => d.type)
                .rollup(leaves => leaves.length)
                .entries(data);

                var lineData = nestData.map(function(d)
                var obj = ;
                obj.date = d.key;
                keys.forEach(function(e)
                obj[e] = d.values.find(function(f)
                return f.key === e
                ).value
                );
                return obj;
                );

                lineData.forEach(function(d)
                d.date = parseTime(d.date);
                )

                console.log("Nested: ", nestData)

                console.log("Mapped: ", lineData)

                <script src="https://d3js.org/d3.v4.min.js"></script>
                <svg></svg>






                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited Feb 8 at 15:42


























                answered Feb 8 at 1:58









                Gerardo Furtado

                1,1442420




                1,1442420






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187018%2frestructuring-a-csv-file-with-d3js%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Chat program with C++ and SFML

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    Will my employers contract hold up in court?