Updating data in 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 this chart I'm calling d3.csv everytime I update the data, which if I understand correctly is a bad thing to do.



In this answer on S.O the answerer explains that d3.csv is asynchronous and the data should only be loaded in once.



I understand why that is, but what I'm wondering now is what is a better way of doing this and if the way that I've done it in the sample code is ever acceptable.



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

<style>

body
margin:auto;
width:850px;
font:10px arial;
padding:25px;
color:#555;

select
border: none;
border-bottom: 1px solid #ccc;
padding: 3px;
text-decoration: none;
font-size: 11px;
cursor: pointer;

select:focus
outline:0;

.sortCheck
float:right;
margin-top:-35px;
margin-right:190px;

#myCheckbox
position:relative;
top:3px;


/* --- Chart Css --- */
.barEnter
fill: steelblue;
opacity: .9;

.barEnter:hover
opacity: 1;

.axis--x path
display: none;

.grid--y path,
.grid--y text
display: none;

.grid--y line
opacity:.15;


</style>

</head>

<body onclick>

<h2 style="font-weight:lighter;">Mulitple datasets test</h2>

<!-- Selection Category -->
<b style="font-size:11px;">
Choose Category
</b>

<select id="category">
<option value=" 1">Category 1</option>
<option value=" 2">Category 2</option>
</select>

<!-- Selection New dataset -->
<span style="margin-left:30px;">
<b style="font-size:11px;">
Choose Year
</b>

<select id="year" onchange="toggle();">
<option value="data2017">2017</option>
<option value="data2016">2016</option>
</select>

</span>

<!-- Chart -->
<div id="chart"></div>

<!-- Sort dimension -->
<span class="sortCheck">Sort Values
<input type="checkbox" id="myCheckbox">
</span>

<script>

let Globalvar = ; // Global access variables

Globalvar.csvShift = "data.csv"; // CSV init

let formatValue = d3.format(",.0f");

let margin = top: 35, right: 145, bottom: 35, left: 45,
width = 700 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;

let x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
y = d3.scaleLinear().rangeRound([height, 0]);

let xAxis = d3.axisBottom(x),
yAxis = d3.axisLeft(y),
yGrid = d3.axisLeft(y).tickSize(-width);

let 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 + ")");

let sideTextX = width + 30,
sideTextY = -height + height;

Globalvar.durations = 0;

function afterLoad()
Globalvar.durations = 750;
;
// Sum of value
g.append("text")
.attr("fill","#555")
.attr("font-weight","bold")
.attr("font-size",11)
.attr("x", sideTextX)
.attr("y", sideTextY)
.text("Accumulated value: ")
g.append("text").attr("id","totalValue")
.attr("fill","#555")
.attr("font-size",11)
.attr("x", sideTextX)
.attr("y", sideTextY + 20);
// Average value
g.append("text")
.attr("fill","#555")
.attr("font-weight","bold")
.attr("font-size",11)
.attr("x", sideTextX)
.attr("y", sideTextY + 40)
.text("Average value: ")
g.append("text").attr("id","avgValue")
.attr("fill","#555")
.attr("font-size",11)
.attr("x", sideTextX)
.attr("y", sideTextY + 60);

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

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

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

// event handlers
d3.select("#myCheckbox").on('change', update);
d3.select("#category").on('change', update);

update();

var file, catInt;

function update()

file = Globalvar.csvShift
catInt = d3.select('#category').property('value');

d3.csv(file, type, function(error,data)

if(error) throw error;

var sortIndex = data.map(function(d) return d.month);

// Update domain
y.domain([0, d3.max(data, function(d)
return d["Category" + catInt]; )
]).nice();

// Update axis
g.selectAll(".axis.axis--y").transition()
.duration(Globalvar.durations)
.call(yAxis);
g.selectAll(".axis.grid--y").transition()
.duration(Globalvar.durations)
.call(yGrid);

// Sums and averages
let sumOfAll = d3.sum(data, function(d)
return d["Category" + catInt];
);
let avgValue = d3.sum(data, function(d)
return d["Category" + catInt];
) / data.length;

//sort data
data.sort( d3.select("#myCheckbox").property("checked")
? function(a, b) return b["Category" + catInt] - a["Category" + catInt];
: function(a, b) return sortIndex.indexOf(a.month) - sortIndex.indexOf(b.month);)

// set x domain
x.domain(data.map(function(d) return d.month; ));

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

// Update rectangles
let bars = g.selectAll(".barEnter")
.data(data, function(d)
return d.month;
);

bars = bars
.enter()
.append("rect")
.attr("class", "barEnter") // Enter data reference
.attr("width", x.bandwidth())
.merge(bars);

bars.transition()
.duration(Globalvar.durations)
.attr("height", function(d)
return height - y(d["Category" + catInt]);
)
.attr("x", function(d)
return x(d.month);
)
.attr("y", function(d)
return y(d["Category" + catInt]);
);

bars.exit().remove();

// Update text on rectangles
let textUpdate = g.selectAll(".textEnter")
.data(data, function(d)
return d.month;
);

textUpdate = textUpdate.enter()
.append("text")
.style("text-shadow","1px 1px #777")
.attr("class", "textEnter") // Enter data reference
.attr("text-anchor","middle")
.attr("font-size",11)
.attr("fill","#fff")
.merge(textUpdate);

textUpdate.transition()
.duration(Globalvar.durations)
.attr("y", function(d)
return y(d["Category" + catInt]) + 15;
)
// Update text value
.text( function(d)
return d["Category" + catInt];
)
.attr("x", function(d)
return x(d.month) + x.bandwidth()/2;
)

// Update sum and avg value
g.selectAll("#totalValue").transition()
.duration(Globalvar.durations)
.text(sumOfAll + " Category " + catInt)
g.selectAll("#avgValue").transition()
.duration(Globalvar.durations)
.text(formatValue(avgValue))

afterLoad()
);


// Initialize csv data
function type(d)
d["Category" + catInt] = +d["Category" + catInt];
return d;

// Toggle csv data
function toggle()
if (document.getElementById('year').value == 'data2017')
Globalvar.csvShift = "data.csv" ;
else if
(document.getElementById('year').value == 'data2016')
Globalvar.csvShift = "data2.csv";
update();



</script>

</body>
</html>






share|improve this question



























    up vote
    2
    down vote

    favorite












    In this chart I'm calling d3.csv everytime I update the data, which if I understand correctly is a bad thing to do.



    In this answer on S.O the answerer explains that d3.csv is asynchronous and the data should only be loaded in once.



    I understand why that is, but what I'm wondering now is what is a better way of doing this and if the way that I've done it in the sample code is ever acceptable.



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

    <style>

    body
    margin:auto;
    width:850px;
    font:10px arial;
    padding:25px;
    color:#555;

    select
    border: none;
    border-bottom: 1px solid #ccc;
    padding: 3px;
    text-decoration: none;
    font-size: 11px;
    cursor: pointer;

    select:focus
    outline:0;

    .sortCheck
    float:right;
    margin-top:-35px;
    margin-right:190px;

    #myCheckbox
    position:relative;
    top:3px;


    /* --- Chart Css --- */
    .barEnter
    fill: steelblue;
    opacity: .9;

    .barEnter:hover
    opacity: 1;

    .axis--x path
    display: none;

    .grid--y path,
    .grid--y text
    display: none;

    .grid--y line
    opacity:.15;


    </style>

    </head>

    <body onclick>

    <h2 style="font-weight:lighter;">Mulitple datasets test</h2>

    <!-- Selection Category -->
    <b style="font-size:11px;">
    Choose Category
    </b>

    <select id="category">
    <option value=" 1">Category 1</option>
    <option value=" 2">Category 2</option>
    </select>

    <!-- Selection New dataset -->
    <span style="margin-left:30px;">
    <b style="font-size:11px;">
    Choose Year
    </b>

    <select id="year" onchange="toggle();">
    <option value="data2017">2017</option>
    <option value="data2016">2016</option>
    </select>

    </span>

    <!-- Chart -->
    <div id="chart"></div>

    <!-- Sort dimension -->
    <span class="sortCheck">Sort Values
    <input type="checkbox" id="myCheckbox">
    </span>

    <script>

    let Globalvar = ; // Global access variables

    Globalvar.csvShift = "data.csv"; // CSV init

    let formatValue = d3.format(",.0f");

    let margin = top: 35, right: 145, bottom: 35, left: 45,
    width = 700 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

    let x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
    y = d3.scaleLinear().rangeRound([height, 0]);

    let xAxis = d3.axisBottom(x),
    yAxis = d3.axisLeft(y),
    yGrid = d3.axisLeft(y).tickSize(-width);

    let 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 + ")");

    let sideTextX = width + 30,
    sideTextY = -height + height;

    Globalvar.durations = 0;

    function afterLoad()
    Globalvar.durations = 750;
    ;
    // Sum of value
    g.append("text")
    .attr("fill","#555")
    .attr("font-weight","bold")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY)
    .text("Accumulated value: ")
    g.append("text").attr("id","totalValue")
    .attr("fill","#555")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 20);
    // Average value
    g.append("text")
    .attr("fill","#555")
    .attr("font-weight","bold")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 40)
    .text("Average value: ")
    g.append("text").attr("id","avgValue")
    .attr("fill","#555")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 60);

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

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

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

    // event handlers
    d3.select("#myCheckbox").on('change', update);
    d3.select("#category").on('change', update);

    update();

    var file, catInt;

    function update()

    file = Globalvar.csvShift
    catInt = d3.select('#category').property('value');

    d3.csv(file, type, function(error,data)

    if(error) throw error;

    var sortIndex = data.map(function(d) return d.month);

    // Update domain
    y.domain([0, d3.max(data, function(d)
    return d["Category" + catInt]; )
    ]).nice();

    // Update axis
    g.selectAll(".axis.axis--y").transition()
    .duration(Globalvar.durations)
    .call(yAxis);
    g.selectAll(".axis.grid--y").transition()
    .duration(Globalvar.durations)
    .call(yGrid);

    // Sums and averages
    let sumOfAll = d3.sum(data, function(d)
    return d["Category" + catInt];
    );
    let avgValue = d3.sum(data, function(d)
    return d["Category" + catInt];
    ) / data.length;

    //sort data
    data.sort( d3.select("#myCheckbox").property("checked")
    ? function(a, b) return b["Category" + catInt] - a["Category" + catInt];
    : function(a, b) return sortIndex.indexOf(a.month) - sortIndex.indexOf(b.month);)

    // set x domain
    x.domain(data.map(function(d) return d.month; ));

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

    // Update rectangles
    let bars = g.selectAll(".barEnter")
    .data(data, function(d)
    return d.month;
    );

    bars = bars
    .enter()
    .append("rect")
    .attr("class", "barEnter") // Enter data reference
    .attr("width", x.bandwidth())
    .merge(bars);

    bars.transition()
    .duration(Globalvar.durations)
    .attr("height", function(d)
    return height - y(d["Category" + catInt]);
    )
    .attr("x", function(d)
    return x(d.month);
    )
    .attr("y", function(d)
    return y(d["Category" + catInt]);
    );

    bars.exit().remove();

    // Update text on rectangles
    let textUpdate = g.selectAll(".textEnter")
    .data(data, function(d)
    return d.month;
    );

    textUpdate = textUpdate.enter()
    .append("text")
    .style("text-shadow","1px 1px #777")
    .attr("class", "textEnter") // Enter data reference
    .attr("text-anchor","middle")
    .attr("font-size",11)
    .attr("fill","#fff")
    .merge(textUpdate);

    textUpdate.transition()
    .duration(Globalvar.durations)
    .attr("y", function(d)
    return y(d["Category" + catInt]) + 15;
    )
    // Update text value
    .text( function(d)
    return d["Category" + catInt];
    )
    .attr("x", function(d)
    return x(d.month) + x.bandwidth()/2;
    )

    // Update sum and avg value
    g.selectAll("#totalValue").transition()
    .duration(Globalvar.durations)
    .text(sumOfAll + " Category " + catInt)
    g.selectAll("#avgValue").transition()
    .duration(Globalvar.durations)
    .text(formatValue(avgValue))

    afterLoad()
    );


    // Initialize csv data
    function type(d)
    d["Category" + catInt] = +d["Category" + catInt];
    return d;

    // Toggle csv data
    function toggle()
    if (document.getElementById('year').value == 'data2017')
    Globalvar.csvShift = "data.csv" ;
    else if
    (document.getElementById('year').value == 'data2016')
    Globalvar.csvShift = "data2.csv";
    update();



    </script>

    </body>
    </html>






    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      In this chart I'm calling d3.csv everytime I update the data, which if I understand correctly is a bad thing to do.



      In this answer on S.O the answerer explains that d3.csv is asynchronous and the data should only be loaded in once.



      I understand why that is, but what I'm wondering now is what is a better way of doing this and if the way that I've done it in the sample code is ever acceptable.



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

      <style>

      body
      margin:auto;
      width:850px;
      font:10px arial;
      padding:25px;
      color:#555;

      select
      border: none;
      border-bottom: 1px solid #ccc;
      padding: 3px;
      text-decoration: none;
      font-size: 11px;
      cursor: pointer;

      select:focus
      outline:0;

      .sortCheck
      float:right;
      margin-top:-35px;
      margin-right:190px;

      #myCheckbox
      position:relative;
      top:3px;


      /* --- Chart Css --- */
      .barEnter
      fill: steelblue;
      opacity: .9;

      .barEnter:hover
      opacity: 1;

      .axis--x path
      display: none;

      .grid--y path,
      .grid--y text
      display: none;

      .grid--y line
      opacity:.15;


      </style>

      </head>

      <body onclick>

      <h2 style="font-weight:lighter;">Mulitple datasets test</h2>

      <!-- Selection Category -->
      <b style="font-size:11px;">
      Choose Category
      </b>

      <select id="category">
      <option value=" 1">Category 1</option>
      <option value=" 2">Category 2</option>
      </select>

      <!-- Selection New dataset -->
      <span style="margin-left:30px;">
      <b style="font-size:11px;">
      Choose Year
      </b>

      <select id="year" onchange="toggle();">
      <option value="data2017">2017</option>
      <option value="data2016">2016</option>
      </select>

      </span>

      <!-- Chart -->
      <div id="chart"></div>

      <!-- Sort dimension -->
      <span class="sortCheck">Sort Values
      <input type="checkbox" id="myCheckbox">
      </span>

      <script>

      let Globalvar = ; // Global access variables

      Globalvar.csvShift = "data.csv"; // CSV init

      let formatValue = d3.format(",.0f");

      let margin = top: 35, right: 145, bottom: 35, left: 45,
      width = 700 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

      let x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
      y = d3.scaleLinear().rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x),
      yAxis = d3.axisLeft(y),
      yGrid = d3.axisLeft(y).tickSize(-width);

      let 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 + ")");

      let sideTextX = width + 30,
      sideTextY = -height + height;

      Globalvar.durations = 0;

      function afterLoad()
      Globalvar.durations = 750;
      ;
      // Sum of value
      g.append("text")
      .attr("fill","#555")
      .attr("font-weight","bold")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY)
      .text("Accumulated value: ")
      g.append("text").attr("id","totalValue")
      .attr("fill","#555")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 20);
      // Average value
      g.append("text")
      .attr("fill","#555")
      .attr("font-weight","bold")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 40)
      .text("Average value: ")
      g.append("text").attr("id","avgValue")
      .attr("fill","#555")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 60);

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

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

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

      // event handlers
      d3.select("#myCheckbox").on('change', update);
      d3.select("#category").on('change', update);

      update();

      var file, catInt;

      function update()

      file = Globalvar.csvShift
      catInt = d3.select('#category').property('value');

      d3.csv(file, type, function(error,data)

      if(error) throw error;

      var sortIndex = data.map(function(d) return d.month);

      // Update domain
      y.domain([0, d3.max(data, function(d)
      return d["Category" + catInt]; )
      ]).nice();

      // Update axis
      g.selectAll(".axis.axis--y").transition()
      .duration(Globalvar.durations)
      .call(yAxis);
      g.selectAll(".axis.grid--y").transition()
      .duration(Globalvar.durations)
      .call(yGrid);

      // Sums and averages
      let sumOfAll = d3.sum(data, function(d)
      return d["Category" + catInt];
      );
      let avgValue = d3.sum(data, function(d)
      return d["Category" + catInt];
      ) / data.length;

      //sort data
      data.sort( d3.select("#myCheckbox").property("checked")
      ? function(a, b) return b["Category" + catInt] - a["Category" + catInt];
      : function(a, b) return sortIndex.indexOf(a.month) - sortIndex.indexOf(b.month);)

      // set x domain
      x.domain(data.map(function(d) return d.month; ));

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

      // Update rectangles
      let bars = g.selectAll(".barEnter")
      .data(data, function(d)
      return d.month;
      );

      bars = bars
      .enter()
      .append("rect")
      .attr("class", "barEnter") // Enter data reference
      .attr("width", x.bandwidth())
      .merge(bars);

      bars.transition()
      .duration(Globalvar.durations)
      .attr("height", function(d)
      return height - y(d["Category" + catInt]);
      )
      .attr("x", function(d)
      return x(d.month);
      )
      .attr("y", function(d)
      return y(d["Category" + catInt]);
      );

      bars.exit().remove();

      // Update text on rectangles
      let textUpdate = g.selectAll(".textEnter")
      .data(data, function(d)
      return d.month;
      );

      textUpdate = textUpdate.enter()
      .append("text")
      .style("text-shadow","1px 1px #777")
      .attr("class", "textEnter") // Enter data reference
      .attr("text-anchor","middle")
      .attr("font-size",11)
      .attr("fill","#fff")
      .merge(textUpdate);

      textUpdate.transition()
      .duration(Globalvar.durations)
      .attr("y", function(d)
      return y(d["Category" + catInt]) + 15;
      )
      // Update text value
      .text( function(d)
      return d["Category" + catInt];
      )
      .attr("x", function(d)
      return x(d.month) + x.bandwidth()/2;
      )

      // Update sum and avg value
      g.selectAll("#totalValue").transition()
      .duration(Globalvar.durations)
      .text(sumOfAll + " Category " + catInt)
      g.selectAll("#avgValue").transition()
      .duration(Globalvar.durations)
      .text(formatValue(avgValue))

      afterLoad()
      );


      // Initialize csv data
      function type(d)
      d["Category" + catInt] = +d["Category" + catInt];
      return d;

      // Toggle csv data
      function toggle()
      if (document.getElementById('year').value == 'data2017')
      Globalvar.csvShift = "data.csv" ;
      else if
      (document.getElementById('year').value == 'data2016')
      Globalvar.csvShift = "data2.csv";
      update();



      </script>

      </body>
      </html>






      share|improve this question













      In this chart I'm calling d3.csv everytime I update the data, which if I understand correctly is a bad thing to do.



      In this answer on S.O the answerer explains that d3.csv is asynchronous and the data should only be loaded in once.



      I understand why that is, but what I'm wondering now is what is a better way of doing this and if the way that I've done it in the sample code is ever acceptable.



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

      <style>

      body
      margin:auto;
      width:850px;
      font:10px arial;
      padding:25px;
      color:#555;

      select
      border: none;
      border-bottom: 1px solid #ccc;
      padding: 3px;
      text-decoration: none;
      font-size: 11px;
      cursor: pointer;

      select:focus
      outline:0;

      .sortCheck
      float:right;
      margin-top:-35px;
      margin-right:190px;

      #myCheckbox
      position:relative;
      top:3px;


      /* --- Chart Css --- */
      .barEnter
      fill: steelblue;
      opacity: .9;

      .barEnter:hover
      opacity: 1;

      .axis--x path
      display: none;

      .grid--y path,
      .grid--y text
      display: none;

      .grid--y line
      opacity:.15;


      </style>

      </head>

      <body onclick>

      <h2 style="font-weight:lighter;">Mulitple datasets test</h2>

      <!-- Selection Category -->
      <b style="font-size:11px;">
      Choose Category
      </b>

      <select id="category">
      <option value=" 1">Category 1</option>
      <option value=" 2">Category 2</option>
      </select>

      <!-- Selection New dataset -->
      <span style="margin-left:30px;">
      <b style="font-size:11px;">
      Choose Year
      </b>

      <select id="year" onchange="toggle();">
      <option value="data2017">2017</option>
      <option value="data2016">2016</option>
      </select>

      </span>

      <!-- Chart -->
      <div id="chart"></div>

      <!-- Sort dimension -->
      <span class="sortCheck">Sort Values
      <input type="checkbox" id="myCheckbox">
      </span>

      <script>

      let Globalvar = ; // Global access variables

      Globalvar.csvShift = "data.csv"; // CSV init

      let formatValue = d3.format(",.0f");

      let margin = top: 35, right: 145, bottom: 35, left: 45,
      width = 700 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

      let x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
      y = d3.scaleLinear().rangeRound([height, 0]);

      let xAxis = d3.axisBottom(x),
      yAxis = d3.axisLeft(y),
      yGrid = d3.axisLeft(y).tickSize(-width);

      let 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 + ")");

      let sideTextX = width + 30,
      sideTextY = -height + height;

      Globalvar.durations = 0;

      function afterLoad()
      Globalvar.durations = 750;
      ;
      // Sum of value
      g.append("text")
      .attr("fill","#555")
      .attr("font-weight","bold")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY)
      .text("Accumulated value: ")
      g.append("text").attr("id","totalValue")
      .attr("fill","#555")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 20);
      // Average value
      g.append("text")
      .attr("fill","#555")
      .attr("font-weight","bold")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 40)
      .text("Average value: ")
      g.append("text").attr("id","avgValue")
      .attr("fill","#555")
      .attr("font-size",11)
      .attr("x", sideTextX)
      .attr("y", sideTextY + 60);

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

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

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

      // event handlers
      d3.select("#myCheckbox").on('change', update);
      d3.select("#category").on('change', update);

      update();

      var file, catInt;

      function update()

      file = Globalvar.csvShift
      catInt = d3.select('#category').property('value');

      d3.csv(file, type, function(error,data)

      if(error) throw error;

      var sortIndex = data.map(function(d) return d.month);

      // Update domain
      y.domain([0, d3.max(data, function(d)
      return d["Category" + catInt]; )
      ]).nice();

      // Update axis
      g.selectAll(".axis.axis--y").transition()
      .duration(Globalvar.durations)
      .call(yAxis);
      g.selectAll(".axis.grid--y").transition()
      .duration(Globalvar.durations)
      .call(yGrid);

      // Sums and averages
      let sumOfAll = d3.sum(data, function(d)
      return d["Category" + catInt];
      );
      let avgValue = d3.sum(data, function(d)
      return d["Category" + catInt];
      ) / data.length;

      //sort data
      data.sort( d3.select("#myCheckbox").property("checked")
      ? function(a, b) return b["Category" + catInt] - a["Category" + catInt];
      : function(a, b) return sortIndex.indexOf(a.month) - sortIndex.indexOf(b.month);)

      // set x domain
      x.domain(data.map(function(d) return d.month; ));

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

      // Update rectangles
      let bars = g.selectAll(".barEnter")
      .data(data, function(d)
      return d.month;
      );

      bars = bars
      .enter()
      .append("rect")
      .attr("class", "barEnter") // Enter data reference
      .attr("width", x.bandwidth())
      .merge(bars);

      bars.transition()
      .duration(Globalvar.durations)
      .attr("height", function(d)
      return height - y(d["Category" + catInt]);
      )
      .attr("x", function(d)
      return x(d.month);
      )
      .attr("y", function(d)
      return y(d["Category" + catInt]);
      );

      bars.exit().remove();

      // Update text on rectangles
      let textUpdate = g.selectAll(".textEnter")
      .data(data, function(d)
      return d.month;
      );

      textUpdate = textUpdate.enter()
      .append("text")
      .style("text-shadow","1px 1px #777")
      .attr("class", "textEnter") // Enter data reference
      .attr("text-anchor","middle")
      .attr("font-size",11)
      .attr("fill","#fff")
      .merge(textUpdate);

      textUpdate.transition()
      .duration(Globalvar.durations)
      .attr("y", function(d)
      return y(d["Category" + catInt]) + 15;
      )
      // Update text value
      .text( function(d)
      return d["Category" + catInt];
      )
      .attr("x", function(d)
      return x(d.month) + x.bandwidth()/2;
      )

      // Update sum and avg value
      g.selectAll("#totalValue").transition()
      .duration(Globalvar.durations)
      .text(sumOfAll + " Category " + catInt)
      g.selectAll("#avgValue").transition()
      .duration(Globalvar.durations)
      .text(formatValue(avgValue))

      afterLoad()
      );


      // Initialize csv data
      function type(d)
      d["Category" + catInt] = +d["Category" + catInt];
      return d;

      // Toggle csv data
      function toggle()
      if (document.getElementById('year').value == 'data2017')
      Globalvar.csvShift = "data.csv" ;
      else if
      (document.getElementById('year').value == 'data2016')
      Globalvar.csvShift = "data2.csv";
      update();



      </script>

      </body>
      </html>








      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 17 at 14:00
























      asked Jan 17 at 12:34









      Robert Andersson

      1667




      1667




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.



          Right now, every time you change the dropdown menu, you call the update function:



          d3.select("#selectbox").on('change', update);


          And then, inside update, you have this:



          function update() 
          d3.csv("data.csv", function(error, data)
          //code here
          )



          Which is not a good design. These are the reasons why:




          1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.

          2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

          All that being said, this is the correct design:



          d3.csv("data.csv", function(error, data) 
          d3.select("#selectbox").on('change', update);

          function update()
          //code here

          )


          Here is your code with that design:






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview






          share|improve this answer























          • Thank you! What if I have more than one csv file? Should I use something like queue().defer?
            – Robert Andersson
            Jan 17 at 13:51






          • 1




            @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
            – Gerardo Furtado
            Jan 17 at 13:52











          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%2f185300%2fupdating-data-in-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










          Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.



          Right now, every time you change the dropdown menu, you call the update function:



          d3.select("#selectbox").on('change', update);


          And then, inside update, you have this:



          function update() 
          d3.csv("data.csv", function(error, data)
          //code here
          )



          Which is not a good design. These are the reasons why:




          1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.

          2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

          All that being said, this is the correct design:



          d3.csv("data.csv", function(error, data) 
          d3.select("#selectbox").on('change', update);

          function update()
          //code here

          )


          Here is your code with that design:






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview






          share|improve this answer























          • Thank you! What if I have more than one csv file? Should I use something like queue().defer?
            – Robert Andersson
            Jan 17 at 13:51






          • 1




            @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
            – Gerardo Furtado
            Jan 17 at 13:52















          up vote
          1
          down vote



          accepted










          Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.



          Right now, every time you change the dropdown menu, you call the update function:



          d3.select("#selectbox").on('change', update);


          And then, inside update, you have this:



          function update() 
          d3.csv("data.csv", function(error, data)
          //code here
          )



          Which is not a good design. These are the reasons why:




          1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.

          2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

          All that being said, this is the correct design:



          d3.csv("data.csv", function(error, data) 
          d3.select("#selectbox").on('change', update);

          function update()
          //code here

          )


          Here is your code with that design:






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview






          share|improve this answer























          • Thank you! What if I have more than one csv file? Should I use something like queue().defer?
            – Robert Andersson
            Jan 17 at 13:51






          • 1




            @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
            – Gerardo Furtado
            Jan 17 at 13:52













          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.



          Right now, every time you change the dropdown menu, you call the update function:



          d3.select("#selectbox").on('change', update);


          And then, inside update, you have this:



          function update() 
          d3.csv("data.csv", function(error, data)
          //code here
          )



          Which is not a good design. These are the reasons why:




          1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.

          2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

          All that being said, this is the correct design:



          d3.csv("data.csv", function(error, data) 
          d3.select("#selectbox").on('change', update);

          function update()
          //code here

          )


          Here is your code with that design:






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview






          share|improve this answer















          Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.



          Right now, every time you change the dropdown menu, you call the update function:



          d3.select("#selectbox").on('change', update);


          And then, inside update, you have this:



          function update() 
          d3.csv("data.csv", function(error, data)
          //code here
          )



          Which is not a good design. These are the reasons why:




          1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.

          2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

          All that being said, this is the correct design:



          d3.csv("data.csv", function(error, data) 
          d3.select("#selectbox").on('change', update);

          function update()
          //code here

          )


          Here is your code with that design:






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview






          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>





          <script src="https://d3js.org/d3.v4.min.js"></script>
          <style>
          body
          font: 10px arial;
          margin: auto;
          position: relative;
          width: 930px;
          padding: 25px;


          .line
          fill: none;
          stroke: #555;
          stroke-width: 1.5px;

          /* === Axis === */

          .axis--y .tick:not(.tick--one) line
          stroke-opacity: .5;
          stroke: #555;
          shape-rendering: crispEdges;


          .tick--one line
          shape-rendering: crispEdges;


          .axis--y path
          display: none;

          /* === Area === */

          .area
          fill-opacity: 0.6;


          .area--below
          fill: darkorange;


          .area--above
          fill: steelblue;

          </style>

          <body>

          Choose a thing
          <select id="selectbox">
          <option value=" 1">Category 1</option>
          <option value=" 2">Category 2</option>
          </select>

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

          <script>
          var csv = `date,Category 1,Category 2
          20111001,63.4,62.7
          20111002,58.0,59.9
          20111003,53.3,59.1
          20111004,55.7,58.8
          20111005,64.2,58.7
          20111006,58.8,57.0
          20111007,57.9,56.7
          20111008,61.8,56.8
          20111009,69.3,56.7
          20111010,71.2,60.1
          20111011,68.7,61.1
          20111012,61.8,61.5
          20111013,63.0,64.3
          20111014,66.9,67.1
          20111015,61.7,64.6
          20111016,61.8,61.6
          20111017,62.8,61.1
          20111018,60.8,59.2
          20111019,62.1,58.9
          20111020,65.1,57.2
          20111021,55.6,56.4
          20111022,54.4,60.7
          20111023,54.4,65.1
          20111024,54.8,60.9
          20111025,57.9,56.1
          20111026,54.6,54.6
          20111027,54.4,56.1
          20111028,42.5,58.1
          20111029,40.9,57.5
          20111030,38.6,57.7
          20111031,44.2,55.1
          20111101,49.6,57.9
          20111102,47.2,64.6
          20111103,50.1,56.2
          20111104,50.1,50.5
          20111105,43.5,51.3
          20111106,43.8,52.6
          20111107,48.9,51.4
          20111108,55.5,50.6
          20111109,53.7,54.6
          20111110,57.7,55.6
          20111111,48.5,53.9
          20111112,46.8,54.0
          20111113,51.1,53.8
          20111114,56.8,53.5
          20111115,59.7,53.4
          20111116,56.5,52.2
          20111117,49.6,52.7
          20111118,41.5,53.1
          20111119,44.3,49.0
          20111120,54.0,50.4
          20111121,54.1,51.1
          20111122,49.4,52.3
          20111123,50.0,54.6
          20111124,44.0,55.1
          20111125,50.3,51.5
          20111126,52.1,53.6
          20111127,49.6,52.3
          20111128,57.2,51.0
          20111129,59.1,49.5
          20111130,50.6,49.8
          20111201,44.3,60.4
          20111202,43.9,62.2
          20111203,42.1,58.3
          20111204,43.9,52.7
          20111205,50.2,51.5
          20111206,54.2,49.9
          20111207,54.6,48.6
          20111208,43.4,46.4
          20111209,42.2,49.8
          20111210,45.0,52.1
          20111211,33.8,48.8
          20111212,36.8,47.4
          20111213,38.6,47.2
          20111214,41.9,46.1
          20111215,49.6,48.8
          20111216,50.2,47.9
          20111217,40.6,49.8
          20111218,29.1,49.1
          20111219,33.7,48.3
          20111220,45.8,49.3
          20111221,47.4,48.4
          20111222,54.4,53.3
          20111223,47.8,47.5
          20111224,34.9,47.9
          20111225,35.9,48.9
          20111226,43.6,45.9
          20111227,42.9,47.2
          20111228,46.2,48.9
          20111229,30.8,50.9
          20111230,40.8,52.9
          20111231,49.8,50.1
          20120101,46.3,53.9
          20120102,43.2,53.1
          20120103,30.3,49.7
          20120104,19.2,52.7
          20120105,32.1,52.6
          20120106,41.2,49.0
          20120107,47.0,51.0
          20120108,46.0,56.8
          20120109,34.7,52.3
          20120110,39.4,51.6
          20120111,40.4,49.8
          20120112,45.4,51.9
          20120113,40.7,53.7
          20120114,30.4,52.9
          20120115,23.9,49.7
          20120116,22.6,45.3
          20120117,39.8,43.6
          20120118,43.2,45.0
          20120119,26.3,47.3
          20120120,32.8,51.4
          20120121,27.4,53.7
          20120122,25.0,48.3
          20120123,39.4,52.9
          20120124,48.7,49.1
          20120125,43.0,52.1
          20120126,37.1,53.6
          20120127,48.2,50.4
          20120128,43.7,50.3
          20120129,40.1,53.8
          20120130,38.0,51.9
          20120131,43.5,50.0
          20120201,50.4,50.0
          20120202,45.8,51.3
          20120203,37.5,51.5
          20120204,40.8,52.0
          20120205,36.5,53.8
          20120206,39.1,54.6
          20120207,43.2,54.3
          20120208,36.5,51.9
          20120209,36.5,53.8
          20120210,38.3,53.9
          20120211,36.9,52.3
          20120212,29.7,50.1
          20120213,33.1,49.5
          20120214,39.6,48.6
          20120215,42.3,49.9
          20120216,39.7,52.4
          20120217,46.0,49.9
          20120218,41.2,51.6
          20120219,39.8,47.8
          20120220,38.1,48.7
          20120221,37.1,49.7
          20120222,45.5,53.4
          20120223,50.6,54.1
          20120224,42.7,55.9
          20120225,42.6,51.7
          20120226,36.9,47.7
          20120227,40.9,45.4
          20120228,45.9,47.0
          20120229,40.7,49.8
          20120301,41.3,48.9
          20120302,36.8,48.1
          20120303,47.6,50.7
          20120304,44.2,55.0
          20120305,38.5,48.8
          20120306,32.9,48.4
          20120307,43.3,49.9
          20120308,51.2,49.2
          20120309,47.8,51.7
          20120310,37.2,49.3
          20120311,42.9,50.0
          20120312,48.8,48.6
          20120313,52.6,53.9
          20120314,60.5,55.2
          20120315,47.2,55.9
          20120316,44.7,54.6
          20120317,48.2,48.2
          20120318,48.2,47.1
          20120319,53.1,45.8
          20120320,57.8,49.7
          20120321,57.5,51.4
          20120322,57.3,51.4
          20120323,61.7,48.4
          20120324,55.8,49.0
          20120325,48.4,46.4
          20120326,49.8,49.7
          20120327,39.6,54.1
          20120328,49.7,54.6
          20120329,56.8,52.3
          20120330,46.5,54.5
          20120331,42.2,56.2
          20120401,45.3,51.1
          20120402,48.1,50.5
          20120403,51.2,52.2
          20120404,61.0,50.6
          20120405,50.7,47.9
          20120406,48.0,47.4
          20120407,51.1,49.4
          20120408,55.7,50.0
          20120409,58.3,51.3
          20120410,55.0,53.8
          20120411,49.0,52.9
          20120412,51.7,53.9
          20120413,53.1,50.2
          20120414,55.2,50.9
          20120415,62.3,51.5
          20120416,62.9,51.9
          20120417,69.3,53.2
          20120418,59.0,53.0
          20120419,54.1,55.1
          20120420,56.5,55.8
          20120421,58.2,58.0
          20120422,52.4,52.8
          20120423,51.6,55.1
          20120424,49.3,57.9
          20120425,52.5,57.5
          20120426,50.5,55.3
          20120427,51.9,53.5
          20120428,47.4,54.7
          20120429,54.1,54.0
          20120430,51.9,53.4
          20120501,57.4,52.7
          20120502,53.7,50.7
          20120503,53.1,52.6
          20120504,57.2,53.4
          20120505,57.0,53.1
          20120506,56.6,56.5
          20120507,54.6,55.3
          20120508,57.9,52.0
          20120509,59.2,52.4
          20120510,61.1,53.4
          20120511,59.7,53.1
          20120512,64.1,49.9
          20120513,65.3,52.0
          20120514,64.2,56.0
          20120515,62.0,53.0
          20120516,63.8,51.0
          20120517,64.5,51.4
          20120518,61.0,52.2
          20120519,62.6,52.4
          20120520,66.2,54.5
          20120521,62.7,52.8
          20120522,63.7,53.9
          20120523,66.4,56.5
          20120524,64.5,54.7
          20120525,65.4,52.5
          20120526,69.4,52.1
          20120527,71.9,52.2
          20120528,74.4,52.9
          20120529,75.9,52.1
          20120530,72.9,52.1
          20120531,72.5,53.3
          20120601,67.2,54.8
          20120602,68.3,54.0
          20120603,67.7,52.3
          20120604,61.9,55.3
          20120605,58.3,53.5
          20120606,61.7,54.1
          20120607,66.7,53.9
          20120608,68.7,54.4
          20120609,72.2,55.0
          20120610,72.6,60.0
          20120611,69.2,57.2
          20120612,66.9,55.1
          20120613,66.7,53.3
          20120614,67.7,53.4
          20120615,68.5,54.6
          20120616,67.5,57.0
          20120617,64.2,55.6
          20120618,61.7,52.5
          20120619,66.4,53.9
          20120620,77.9,55.3
          20120621,88.3,53.3
          20120622,82.2,54.1
          20120623,77.0,55.2
          20120624,75.4,55.8
          20120625,70.9,56.8
          20120626,65.9,57.5
          20120627,73.5,57.7
          20120628,77.4,56.6
          20120629,79.6,56.4
          20120630,84.2,58.4
          20120701,81.8,58.8
          20120702,82.5,56.4
          20120703,80.2,56.5
          20120704,77.8,55.8
          20120705,86.1,54.8
          20120706,79.9,54.9
          20120707,83.5,54.7
          20120708,81.5,52.8
          20120709,77.8,53.7
          20120710,76.1,53.1
          20120711,76.3,52.7
          20120712,75.8,52.0
          20120713,77.2,53.4
          20120714,79.3,54.0
          20120715,78.9,54.0
          20120716,79.6,54.5
          20120717,83.3,56.7
          20120718,84.3,57.5
          20120719,75.1,57.1
          20120720,68.4,58.1
          20120721,68.4,57.6
          20120722,72.2,56.0
          20120723,75.6,56.6
          20120724,82.6,57.8
          20120725,78.4,57.5
          20120726,77.0,56.4
          20120727,79.4,55.3
          20120728,77.4,55.0
          20120729,72.5,55.6
          20120730,72.9,55.6
          20120731,73.6,55.9
          20120801,75.0,55.4
          20120802,77.7,54.4
          20120803,79.7,53.7
          20120804,79.6,54.1
          20120805,81.5,57.8
          20120806,80.0,58.2
          20120807,75.7,58.0
          20120808,77.8,57.0
          20120809,78.6,55.0
          20120810,77.8,54.8
          20120811,78.5,53.0
          20120812,78.8,52.5
          20120813,78.6,53.3
          20120814,76.8,53.9
          20120815,76.7,56.2
          20120816,75.9,57.1
          20120817,77.6,55.3
          20120818,72.6,56.2
          20120819,70.4,54.3
          20120820,71.8,53.1
          20120821,73.6,53.4
          20120822,74.7,54.5
          20120823,74.6,55.7
          20120824,76.0,54.8
          20120825,76.2,53.8
          20120826,73.4,56.5
          20120827,74.6,58.3
          20120828,79.4,58.7
          20120829,74.7,57.5
          20120830,73.5,55.9
          20120831,77.9,55.4
          20120901,80.7,55.7
          20120902,75.1,53.1
          20120903,73.5,53.5
          20120904,73.5,52.5
          20120905,77.7,54.5
          20120906,74.2,56.3
          20120907,76.0,56.4
          20120908,77.1,56.5
          20120909,69.7,56.4
          20120910,67.8,55.4
          20120911,64.0,56.2
          20120912,68.1,55.7
          20120913,69.3,54.3
          20120914,70.0,55.2
          20120915,69.3,54.3
          20120916,66.3,52.9
          20120917,67.0,54.8
          20120918,72.8,54.8
          20120919,67.2,56.8
          20120920,62.1,55.4
          20120921,64.0,55.8
          20120922,65.5,55.9
          20120923,65.7,52.8
          20120924,60.4,54.5
          20120925,63.2,53.3
          20120926,68.5,53.6
          20120927,69.2,52.1
          20120928,68.7,52.6
          20120929,62.5,53.9
          20120930,62.3,55.1`;


          var margin =
          top: 20,
          right: 80,
          bottom: 30,
          left: 45
          ,
          width = 960 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

          var parseDate = d3.timeParse("%Y%m%d");

          var formatPercent = d3.format("+.0%"),
          formatValue = d3.format(",.1f"),
          formatChange = function(x)
          return formatPercent(x - 1);
          ;

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

          var xAxis = d3.axisBottom(x),
          yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

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

          var area = d3.area()
          .curve(d3.curveCardinal)
          .x(function(d)
          return x(d.date);
          )
          .y1(function(d)
          return y(d.city);
          );

          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 gY = g.append("g")
          .attr("class", "axis axis--y");

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

          var defs = g.append("defs");

          var durations = 0;

          var afterLoad = () => durations = 750;

          var data = d3.csvParse(csv, function(d, _, columns)
          d.date = parseDate(d.date);
          for (var i = 1, n = columns.length, c; i < n; ++i)
          d[c = columns[i]] = +d[c];
          return d;
          )

          update();

          var VALUE, baseValue;

          function update()

          d3.selectAll('clipPath').remove();

          VALUE = d3.select('#selectbox').property('value');

          baseValue = data[0]["Category" + VALUE];

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

          var copy = ;

          keys.forEach(function(t)
          t = t.slice(0, -2) // Slice last two letters
          copy.push(t) // Push sliced strings into copy array
          );

          var cities = copy.map(function(id)
          return
          id: id,
          values: data.map(function(d)
          return
          date: d.date,
          city: d[id + VALUE] / baseValue
          ;
          )
          ;
          );

          x.domain(d3.extent(data, function(d)
          return d.date;
          ));

          y.domain([
          d3.min(cities, function(c)
          return d3.min(c.values, function(d)
          return d.city;
          );
          ),
          d3.max(cities, function(c)
          return d3.max(c.values, function(d)
          return d.city;
          );
          )
          ]).nice();

          area.y0(y(1));

          yAxis.tickValues(d3.scaleLinear()
          .domain(y.domain())
          .ticks(10));

          gY.transition().duration(durations).call(yAxis);

          gY.selectAll(".tick")
          .classed("tick--one", function(d)
          return Math.abs(d - 1) < 1e-6;
          );

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

          defs.append("clipPath")
          .attr("id", "clip-above")
          .append("rect");

          g.selectAll("#clip-above>rect")
          .transition().duration(durations)
          .attr("width", width)
          .attr("height", y(1));

          defs.append("clipPath")
          .attr("id", "clip-below")
          .append("rect");

          g.selectAll("#clip-below>rect")
          .transition().duration(durations)
          .attr("y", y(1))
          .attr("width", width)
          .attr("height", height - y(1));

          // ========= Above Clip =========

          var above = g.selectAll(".above")
          .data(cities);

          above = above
          .enter()
          .append("path")
          .attr("class", "area area--above above")
          .attr("clip-path", "url(#clip-above)")
          .merge(above);

          above.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-above)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Below Clip =========

          var below = g.selectAll(".below")
          .data(cities);

          below = below
          .enter()
          .append("path")
          .attr("class", "area area--below below")
          .attr("clip-path", "url(#clip-below)")
          .merge(below);

          below.transition()
          .duration(durations)
          .attr("clip-path", "url(#clip-below)")
          .attr("d", function(d)
          return area(d.values)
          );

          // ========= Line Path =========

          var cityLine = g.selectAll(".cities")
          .data(cities);

          cityLine = cityLine
          .enter()
          .append("path")
          .attr("class", "line cities")
          .merge(cityLine);

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

          afterLoad();

          d3.select("#selectbox").on('change', update);


          </script>
          </body>






          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Jan 17 at 14:26


























          answered Jan 17 at 13:44









          Gerardo Furtado

          1,1442420




          1,1442420











          • Thank you! What if I have more than one csv file? Should I use something like queue().defer?
            – Robert Andersson
            Jan 17 at 13:51






          • 1




            @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
            – Gerardo Furtado
            Jan 17 at 13:52

















          • Thank you! What if I have more than one csv file? Should I use something like queue().defer?
            – Robert Andersson
            Jan 17 at 13:51






          • 1




            @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
            – Gerardo Furtado
            Jan 17 at 13:52
















          Thank you! What if I have more than one csv file? Should I use something like queue().defer?
          – Robert Andersson
          Jan 17 at 13:51




          Thank you! What if I have more than one csv file? Should I use something like queue().defer?
          – Robert Andersson
          Jan 17 at 13:51




          1




          1




          @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
          – Gerardo Furtado
          Jan 17 at 13:52





          @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908
          – Gerardo Furtado
          Jan 17 at 13:52













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185300%2fupdating-data-in-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?