D3:如何对多系列折线图使用exit()。remove()

时间:2017-03-10 15:52:12

标签: javascript d3.js

对于d3(d3.v4.js)的多系列折线图:

https://bl.ocks.org/mbostock/3884955

如果我想用不同的输入数据重绘图表,如何应用exit().remove()功能?

function myGraphic(myData) {
    var svg = d3.select("svg"),
        margin = {top: 20, right: 80, bottom: 30, left: 50},
        width = svg.attr("width") - margin.left - margin.right,
        height = svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");


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

    var line = d3.line()
        .x(function (d) {
            return x(d.date);
        })
        .y(function (d) {
            return y(d.temperature);
        });

    //noinspection JSUnresolvedVariable
    var data = myData.dataList;

    //noinspection JSUnresolvedVariable
    data.columns = ["date", "value1", myData.referenceName];

    var cities = data.columns.slice(1).map(function (id) {
        return {
            id: id,
            values: data.map(function (d) {
                return {date: d.date, temperature: d[id]};
            })
        };
    });


    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.temperature;
            });
        }),
        d3.max(cities, function (c) {
            return d3.max(c.values, function (d) {
                return d.temperature;
            });
        })
    ]);

    z.domain(cities.map(function (c) {
        return c.id;
    }));

    var xAxisScale2 = d3.scaleTime()
        .domain([new Date(2014, 0, 1), new Date(2016, 0, 1, 0)])
        .rangeRound([20, width - 20]);

    var xAxis = d3.axisBottom(x);


    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis.ticks(d3.timeYear));

    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", "0.71em")
        .attr("fill", "#000")
        .text("Temperature");


    var city = g.selectAll(".city")
        .data(cities)
        .enter().append("g")
        .attr("class", "city");


    city.append("path")
        .attr("class", "line")
        .attr("d", function (d) {
            return line(d.values);
        })
        .style("stroke", function (d) {
            return z(d.id);
        });

    city.append("text")
        .datum(function (d) {
            return {id: d.id, value: d.values[d.values.length - 1]};
        })
        .attr("transform", function (d) {
            return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
        })
        .attr("x", 3)
        .attr("dy", "0.35em")
        .style("font", "10px sans-serif")
        .text(function (d) {
            return d.id;
        });

    city.exit().remove();

}

更新:

我尝试合并提案of @Gerardo Furtado,但似乎有些事情在这里仍然存在错误:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

    .axis--x path {
        display: none;
    }

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

</style>
<button>Click me</button>
<svg width="960" height="500"></svg>
<!--<script src="//d3js.org/d3.v4.min.js"></script>-->
<script src="d3.v4.js"></script>

<!--<script src="v03-exit-funktioniert-3-evolution.js"></script>-->

<script>

    var svg = d3.select("svg"),
        margin = {top: 20, right: 80, bottom: 30, left: 50},
        width = svg.attr("width") - margin.left - margin.right,
        height = svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

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

    var line = d3.line()
        .curve(d3.curveBasis)
        .x(function (d) {
            return x(d.date);
        })
        .y(function (d) {
            return y(d.temperature);
        });

    var data = [
        {"date": "1136156400000", "New York": 63.4, "San Francisco": 62.7, "Austin": 72.2},
        {"date": "1167692400000", "New York": 58.0, "San Francisco": 59.9, "Austin": 67.7},
        {"date": "1199228400000", "New York": 53.3, "San Francisco": 59.1, "Austin": 69.4},
        {"date": "1230850800000", "New York": 55.7, "San Francisco": 58.8, "Austin": 68.0},
        {"date": "1262386800000", "New York": 62.3, "San Francisco": 55.1, "Austin": 71.9}];

    var data2 = [
        {"date": "1136156400000", "New York": 163.4, "San Francisco": 262.7, "Austin": 372.2},
        {"date": "1167692400000", "New York": 158.0, "San Francisco": 259.9, "Austin": 367.7},
        {"date": "1199228400000", "New York": 153.3, "San Francisco": 259.1, "Austin": 369.4},
        {"date": "1230850800000", "New York": 155.7, "San Francisco": 258.8, "Austin": 368.0},
        {"date": "1262386800000", "New York": 162.3, "San Francisco": 255.1, "Austin": 371.9}];


    // d3.tsv("data.tsv", type, function (error, data) {
    //     if (error) throw error;

    data.columns = ["date", "New York", "San Francisco", "Austin"];

    var cities = data.columns.slice(1).map(function (id) {
        return {
            id: id,
            values: data.map(function (d) {
                return {date: d.date, temperature: d[id]};
            })
        };
    });

    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.temperature;
            });
        }),
        d3.max(cities, function (c) {
            return d3.max(c.values, function (d) {
                return d.temperature;
            });
        })
    ]);
    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));
    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", "0.71em")
        .attr("fill", "#000")
        .text("Temperature, ºF");
    update();
    d3.select("button").on("click", function () {
        // cities.splice(0, 1);
        data = data2;
        console.log(cities);
//            console.log(JSON.stringify(cities));
        update();
    });

    function update() {
        data.columns = ["date", "New York", "San Francisco", "Austin"];
        cities = data.columns.slice(1).map(function (id) {
            return {
                id: id,
                values: data.map(function (d) {
                    return {date: d.date, temperature: d[id]};
                })
            };
        });


        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.temperature;
                });
            }),
            d3.max(cities, function (c) {
                return d3.max(c.values, function (d) {
                    return d.temperature;
                });
            })
        ]);
        z.domain(cities.map(function (c) {
            return c.id;
        }));
        var city = g.selectAll(".city")
            .data(cities);
        city.exit().remove();
        var cityEnter = city.enter().append("g")
            .attr("class", "city");
        cityEnter.append("path")
            .attr("class", "line")
            .attr("d", function (d) {
                return line(d.values);
            })
            .style("stroke", function (d) {
                return z(d.id);
            });
        cityEnter.append("text")
            .datum(function (d) {
                return {id: d.id, value: d.values[d.values.length - 1]};
            })
            .attr("transform", function (d) {
                return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
            })
            .attr("x", 3)
            .attr("dy", "0.35em")
            .style("font", "10px sans-serif")
            .text(function (d) {
                return d.id;
            });
    }
    // });

    function type(d, _, columns) {
        d.date = parseTime(d.date);
        for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
        return d;
    }


</script> 

UPDATE2:

(希望)只有一个关于标签名称及其位置的主题:

<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
    .axis--x path {
        display: none;
    }

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

</style>
<button>Click me</button>
<svg width="960" height="500"></svg>
<!--<script src="//d3js.org/d3.v4.min.js"></script>-->
<script src="d3.v4.js"></script>

<!--<script src="v03-exit-funktioniert-3-evolution.js"></script>-->

<script>
    var svg = d3.select("svg"),
        margin = {
            top: 20,
            right: 80,
            bottom: 30,
            left: 50
        },
        width = svg.attr("width") - margin.left - margin.right,
        height = svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

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

    var line = d3.line()
        .curve(d3.curveBasis)
        .x(function (d) {
            return x(d.date);
        })
        .y(function (d) {
            return y(d.temperature);
        });

    var data = [{
        "date": "1136156400000",
        "Old York": 63.4,
        "San Francisco": 62.7,
        "Austin": 72.2
    }, {
        "date": "1167692400000",
        "Old York": 58.0,
        "San Francisco": 59.9,
        "Austin": 67.7
    }, {
        "date": "1199228400000",
        "Old York": 53.3,
        "San Francisco": 59.1,
        "Austin": 69.4
    }, {
        "date": "1230850800000",
        "Old York": 55.7,
        "San Francisco": 58.8,
        "Austin": 68.0
    }, {
        "date": "1262386800000",
        "Old York": 62.3,
        "San Francisco": 55.1,
        "Austin": 71.9
    }];

    var data2 = [{
        "date": "1136156400000",
        "New York": 263.4,
        "San Francisco": 262.7,
        "Austin": 372.2
    }, {
        "date": "1167692400000",
        "New York": 458.0,
        "San Francisco": 259.9,
        "Austin": -367.7
    }, {
        "date": "1199228400000",
        "New York": 153.3,
        "San Francisco": 259.1,
        "Austin": 369.4
    }, {
        "date": "1230850800000",
        "New York": 155.7,
        "San Francisco": 258.8,
        "Austin": 368.0
    }, {
        "date": "1262386800000",
        "New York": 162.3,
        "San Francisco": 255.1,
        "Austin": 371.9
    }];


    // d3.tsv("data.tsv", type, function (error, data) {
    //     if (error) throw error;

    data.columns = ["date", "Old York", "San Francisco", "Austin"];

    var cities = data.columns.slice(1).map(function (id) {
        return {
            id: id,
            values: data.map(function (d) {
                return {
                    date: d.date,
                    temperature: d[id]
                };
            })
        };
    });

    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.temperature;
            });
        }),
        d3.max(cities, function (c) {
            return d3.max(c.values, function (d) {
                return d.temperature;
            });
        })
    ]);
    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));
    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", "0.71em")
        .attr("fill", "#000")
        .text("Temperature, ºF");
    update();
    d3.select("button").on("click", function () {
        // cities.splice(0, 1);
        data = data2;
        data.columns = ["date", "New York", "San Francisco", "Austin"];
        //            console.log(JSON.stringify(cities));
        update();
    });

    function update() {
        cities = data.columns.slice(1).map(function (id) {
            return {
                id: id,
                values: data.map(function (d) {
                    return {
                        date: d.date,
                        temperature: d[id]
                    };
                })
            };
        });


        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.temperature;
                });
            }),
            d3.max(cities, function (c) {
                return d3.max(c.values, function (d) {
                    return d.temperature;
                });
            })
        ]);
        z.domain(cities.map(function (c) {
            return c.id;
        }));
        var city = g.selectAll(".city")
            .data(cities);

        city.exit().remove();

        var cityEnter = city.enter().append("g")
            .attr("class", "city");

        cityEnter.append("path")
            .attr("class", "line")
            .attr("d", function (d) {
                return line(d.values);
            })
            .style("stroke", function (d) {
                return z(d.id);
            });

        cityEnter.append("text")
            .datum(function (d) {
                return {
                    id: d.id,
                    value: d.values[d.values.length - 1]
                };
            })
            .attr("transform", function (d) {
                return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
            })
            .attr("x", 3)
            .attr("dy", "0.35em")
            .style("font", "10px sans-serif")
            .text(function (d) {
                return d.id;
            });

        city = cityEnter.merge(city);

        city.select("path").attr("d", function (d) {
            return line(d.values);
        });

        svg.select(".axis--y").call(d3.axisLeft(y))
    }
    // });

    function type(d, _, columns) {
        d.date = parseTime(d.date);
        for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
        return d;
    }

</script>

UPDATE3: 试试标签(纽约与纽约) - 还没有工作......

<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
    .axis--x path {
        display: none;
    }

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

</style>
<button>Click me</button>
<svg width="960" height="500"></svg>
<!--<script src="d3.v4.js"></script>-->

<script>
    var svg = d3.select("svg"),
        margin = {
            top: 20,
            right: 80,
            bottom: 30,
            left: 50
        },
        width = svg.attr("width") - margin.left - margin.right,
        height = svg.attr("height") - margin.top - margin.bottom,
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

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

    var line = d3.line()
        .curve(d3.curveBasis)
        .x(function (d) {
            return x(d.date);
        })
        .y(function (d) {
            return y(d.temperature);
        });

    var data = [{
        "date": "1136156400000",
        "Old York": 63.4,
        "San Francisco": 62.7,
        "Austin": 72.2
    }, {
        "date": "1167692400000",
        "Old York": 58.0,
        "San Francisco": 59.9,
        "Austin": 67.7
    }, {
        "date": "1199228400000",
        "Old York": 53.3,
        "San Francisco": 59.1,
        "Austin": 69.4
    }, {
        "date": "1230850800000",
        "Old York": 55.7,
        "San Francisco": 58.8,
        "Austin": 68.0
    }, {
        "date": "1262386800000",
        "Old York": 62.3,
        "San Francisco": 55.1,
        "Austin": 71.9
    }];

    var data2 = [{
        "date": "1136156400000",
        "New York": 263.4,
        "San Francisco": 262.7,
        "Austin": 372.2
    }, {
        "date": "1167692400000",
        "New York": 458.0,
        "San Francisco": 259.9,
        "Austin": -367.7
    }, {
        "date": "1199228400000",
        "New York": 153.3,
        "San Francisco": 259.1,
        "Austin": 369.4
    }, {
        "date": "1230850800000",
        "New York": 155.7,
        "San Francisco": 258.8,
        "Austin": 368.0
    }, {
        "date": "1262386800000",
        "New York": 162.3,
        "San Francisco": 255.1,
        "Austin": 371.9
    }];


    // d3.tsv("data.tsv", type, function (error, data) {
    //     if (error) throw error;

    data.columns = ["date", "Old York", "San Francisco", "Austin"];

    var cities = data.columns.slice(1).map(function (id) {
        return {
            id: id,
            values: data.map(function (d) {
                return {
                    date: d.date,
                    temperature: d[id]
                };
            })
        };
    });

    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.temperature;
            });
        }),
        d3.max(cities, function (c) {
            return d3.max(c.values, function (d) {
                return d.temperature;
            });
        })
    ]);
    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));
    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", "0.71em")
        .attr("fill", "#000")
        .text("Temperature, ºF");

    update();
    d3.select("button").on("click", function () {
        // cities.splice(0, 1);
        data = data2;
        data.columns = ["date", "New York", "San Francisco", "Austin"];
        //            console.log(JSON.stringify(cities));
        update();
    });

    function update() {
//        data.columns = ["date", "New York", "San Francisco", "Austin"];
        cities = data.columns.slice(1).map(function (id) {
            return {
                id: id,
                values: data.map(function (d) {
                    return {
                        date: d.date,
                        temperature: d[id]
                    };
                })
            };
        });


        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.temperature;
                });
            }),
            d3.max(cities, function (c) {
                return d3.max(c.values, function (d) {
                    return d.temperature;
                });
            })
        ]);
        z.domain(cities.map(function (c) {
            return c.id;
        }));

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

        city.append("text")
            .datum(function (d) {
                return {
                    id: d.id,
                    value: d.values[d.values.length - 1]
                };
            })
            .attr("transform", function (d) {
                return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
            })
            .attr("x", 3)
            .attr("dy", "0.35em")
            .style("font", "10px sans-serif")
            .text(function (d) {
                return d.id;
            });

        // var text = g.selectAll(".text")
        //     .data(texts);

        city.exit().remove();

        var cityEnter = city.enter().append("g")
            .attr("class", "city");

        cityEnter.append("path")
            .attr("class", "line")
            .attr("d", function (d) {
                return line(d.values);
            })
            .style("stroke", function (d) {
                return z(d.id);
            });


        city = cityEnter.merge(city);

        cityEnter.append("text")
        //        city.append("text")
            .datum(function (d) {
                return {
                    id: d.id,
                    value: d.values[d.values.length - 1]
                };
            })
            .attr("transform", function (d) {
                return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
            })
            .attr("x", 3)
            .attr("dy", "0.35em")
            .style("font", "10px sans-serif")
            .text(function (d) {
                return d.id;
            });


        city.select("path")
        //            .transition().duration(1000)
            .attr("d", function (d) {
                return line(d.values);
            });

        city.select("text").datum(function (d) {
            return {
                id: d.id,
                value: d.values[d.values.length - 1]
            };
        })
        //            .transition().duration(1000)
            .attr("transform", function (d) {
                return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
            });

        svg.select(".axis--y")
        //            .transition().duration(1000)
            .call(d3.axisLeft(y));
    }

</script>

1 个答案:

答案 0 :(得分:2)

现在你只是在Bostock代码的末尾添加这一行:

city.exit().remove();

然而,这不起作用,因为他的代码只有一个“输入”选择。

解决方案是创建数据绑定选择和分离的“输入”选择。这样,您将有一个工作“退出”选择:

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

city.exit().remove();

var cityEnter = city.enter().append("g")
    .attr("class", "city");

cityEnter.append("path")
    //etc...

cityEnter.append("text")
    //etc..

这是一个带有该更改的演示bl.ocks,每次单击顶部的按钮时,它会删除数据数组中的第一个对象,退出选择将删除该行:

https://bl.ocks.org/anonymous/98204ee0226e2f6178154b7903f9ef99

编辑:在原始问题中,您只询问退出选择。由于您实际上询问更新选择,这是一个新的演示,更新行,文本和轴:

<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
  .axis--x path {
    display: none;
  }
  
  .line {
    fill: none;
    stroke: steelblue;
    stroke-width: 1.5px;
  }

</style>
<button>Click me</button>
<svg width="960" height="500"></svg>
<!--<script src="//d3js.org/d3.v4.min.js"></script>-->
<script src="d3.v4.js"></script>

<!--<script src="v03-exit-funktioniert-3-evolution.js"></script>-->

<script>
  var svg = d3.select("svg"),
    margin = {
      top: 20,
      right: 80,
      bottom: 30,
      left: 50
    },
    width = svg.attr("width") - margin.left - margin.right,
    height = svg.attr("height") - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

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

  var line = d3.line()
    .curve(d3.curveBasis)
    .x(function(d) {
      return x(d.date);
    })
    .y(function(d) {
      return y(d.temperature);
    });

  var data = [{
    "date": "1136156400000",
    "New York": 63.4,
    "San Francisco": 62.7,
    "Austin": 72.2
  }, {
    "date": "1167692400000",
    "New York": 58.0,
    "San Francisco": 59.9,
    "Austin": 67.7
  }, {
    "date": "1199228400000",
    "New York": 53.3,
    "San Francisco": 59.1,
    "Austin": 69.4
  }, {
    "date": "1230850800000",
    "New York": 55.7,
    "San Francisco": 58.8,
    "Austin": 68.0
  }, {
    "date": "1262386800000",
    "New York": 62.3,
    "San Francisco": 55.1,
    "Austin": 71.9
  }];

  var data2 = [{
    "date": "1136156400000",
    "New York": 163.4,
    "San Francisco": 262.7,
    "Austin": 372.2
  }, {
    "date": "1167692400000",
    "New York": 158.0,
    "San Francisco": 259.9,
    "Austin": 367.7
  }, {
    "date": "1199228400000",
    "New York": 153.3,
    "San Francisco": 259.1,
    "Austin": 369.4
  }, {
    "date": "1230850800000",
    "New York": 155.7,
    "San Francisco": 258.8,
    "Austin": 368.0
  }, {
    "date": "1262386800000",
    "New York": 162.3,
    "San Francisco": 255.1,
    "Austin": 371.9
  }];


  // d3.tsv("data.tsv", type, function (error, data) {
  //     if (error) throw error;

  data.columns = ["date", "New York", "San Francisco", "Austin"];

  var cities = data.columns.slice(1).map(function(id) {
    return {
      id: id,
      values: data.map(function(d) {
        return {
          date: d.date,
          temperature: d[id]
        };
      })
    };
  });

  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.temperature;
      });
    }),
    d3.max(cities, function(c) {
      return d3.max(c.values, function(d) {
        return d.temperature;
      });
    })
  ]);
  g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x));
  g.append("g")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y))
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.71em")
    .attr("fill", "#000")
    .text("Temperature, ºF");
  update();
  d3.select("button").on("click", function() {
    // cities.splice(0, 1);
    data = data2;
    //            console.log(JSON.stringify(cities));
    update();
  });

  function update() {
    data.columns = ["date", "New York", "San Francisco", "Austin"];
    cities = data.columns.slice(1).map(function(id) {
      return {
        id: id,
        values: data.map(function(d) {
          return {
            date: d.date,
            temperature: d[id]
          };
        })
      };
    });


    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.temperature;
        });
      }),
      d3.max(cities, function(c) {
        return d3.max(c.values, function(d) {
          return d.temperature;
        });
      })
    ]);
    z.domain(cities.map(function(c) {
      return c.id;
    }));
    var city = g.selectAll(".city")
      .data(cities);

    city.exit().remove();

    var cityEnter = city.enter().append("g")
      .attr("class", "city");

    cityEnter.append("path")
      .attr("class", "line")
      .attr("d", function(d) {
        return line(d.values);
      })
      .style("stroke", function(d) {
        return z(d.id);
      });

    cityEnter.append("text")
      .datum(function(d) {
        return {
          id: d.id,
          value: d.values[d.values.length - 1]
        };
      })
      .attr("transform", function(d) {
        return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
      })
      .attr("x", 3)
      .attr("dy", "0.35em")
      .style("font", "10px sans-serif")
      .text(function(d) {
        return d.id;
      });

    city = cityEnter.merge(city);

    city.select("path").transition().duration(1000).attr("d", function(d) {
      return line(d.values);
    });

    city.select("text").datum(function(d) {
        return {
          id: d.id,
          value: d.values[d.values.length - 1]
        };
      }).transition().duration(1000)
      .attr("transform", function(d) {
        return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
      })

    svg.select(".axis--y").transition().duration(1000).call(d3.axisLeft(y))
  }
  // });

  function type(d, _, columns) {
    d.date = parseTime(d.date);
    for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
    return d;
  }

</script>