数据可视化从入门到精通:JavaScript、D3.js、Plotly 等可视化库的实战应用

1,931 阅读4分钟

一、数据可视化的基础知识

在学习任何可视化库之前,我们需要掌握一些基本概念,其中包括:

  1. 编程语言:JavaScript 是最常用的编程语言之一,用于编写许多数据可视化库。如果您已经熟悉 JavaScript,则可以跳过这一步骤。
  2. 数据分析和统计学:了解基本的数据分析和统计学概念,如数据类型、均值、中位数、标准差、相关性等。
  3. 图表类型:了解数据可视化中的不同图表类型及其应用场景,如直方图、散点图、折线图、条形图、饼图等。
  4. 数据可视化框架:了解一些常用的可视化框架,如 D3.js、Plotly 等。这些框架提供了大量的图表类型和交互功能,使我们可以轻松地创建交互式可视化。

二、什么是JavaScript

JavaScript 是一种常用的编程语言,能够处理各种数据类型、创建动态效果,这些都是数据可视化中的重要组成部分。在学习数据可视化之前,您需要学习 JavaScript 的语法、基本数据结构和 DOM 操作。

您可以通过以下途径学习 JavaScript:

  1. 在线编程平台:例如 Codecademy、FreeCodeCamp、W3Schools 等平台提供免费的 JavaScript 课程和实践项目,可以加强您的实践。
  2. 书籍和教程:JavaScript 语言由 Douglas Crockford、Eloquent JavaScript 等著名作者写过令人信服的书籍和教程。
  3. 练习项目:起初,您可以从简单的练习项目开始,例如制作一个简单的 To-do List 应用程序,然后尝试编写更复杂的应用程序。

三、什么是D3.js

D3.js 是一种常用的数据可视化库,它是 Data-Driven Documents 的缩写,开发人员可以使用它创建各种图表类型。

04022.jpg

您可以通过以下途径学习 D3.js:

  1. 官方文档:D3.js 官网提供了完整的文档和示例,可以帮助您了解 D3.js 的各种特性和用法。
  2. 书籍和教程:D3.js 有一些非常好的书籍和在线教程,如 Data Visualization with D3.js、D3.js Tips and Tricks,等等。
  3. 练习项目:创建一个简单的数据可视化项目,如制作一个散点图或折线图。一旦您掌握了基础知识,就可以挑战更复杂的图表类型,如力导向图或地图。

四、什么是Plotly

Plotly 是另一个常用的数据可视化库,它提供了许多可视化功能,包括交互式图表、地图和 Dash 仪表板等。Plotly 具有跨平台性,支持 Python、R、JavaScript 和 MATLAB 等多种语言。

您可以使用以下途径学习 Plotly:

  1. 官方文档:Plotly 官网提供了完整的文档和示例,可以帮助您了解 Plotly 的各种特性和用法。
  2. 书籍和教程:Plotly 有一些非常好的书籍和在线教程,如 Plotly Fundamentals、Plotly Dash and Flask Tutorials 等。
  3. 练习项目:创建一个简单的数据可视化项目,如制作一个散点图或折线图。一旦您掌握了基础知识,就可以挑战更复杂的图表类型,如地图、3D 图表或交互式仪表板。

五、JavaScript 的实战应用

5.1 创建一个简单的散点图

散点图是一种用于显示两个数值变量之间关系的常用图表类型。下面是一个用 JavaScript 创建散点图的示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>Scatter Plot Example</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <div id="scatterplot"></div>
    <script>
        // 定义数据
        var data = [
            { x: 10, y: 20 },
            { x: 20, y: 30 },
            { x: 30, y: 40 },
            { x: 40, y: 50 },
            { x: 50, y: 60 }
        ];

        // 创建画布
        var margin = { top: 20, right: 20, bottom: 20, left: 20 };
        var width = 500 - margin.left - margin.right;
        var height = 400 - margin.top - margin.bottom;

        var svg = d3.select("#scatterplot")
                    .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 xScale = d3.scaleLinear()
                        .domain([0, 50])
                        .range([0, width]);

        var yScale = d3.scaleLinear()
                        .domain([0, 80])
                        .range([height, 0]);

        // 绘制散点图
        svg.selectAll(".dot")
            .data(data)
            .enter()
            .append("circle")
            .attr("class", "dot")
            .attr("cx", function(d) { return xScale(d.x); })
            .attr("cy", function(d) { return yScale(d.y); })
            .attr("r", 5);
    </script>
</body>
</html>

5.2 创建一个简单的条形图

条形图是用于比较多个类别数据之间差异的一种图表类型。下面是一个用 JavaScript 创建条形图的示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>Bar Chart Example</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <div id="barchart"></div>
    <script>
        // 定义数据
        var data = [
            { category: "A", value: 10 },
            { category: "B", value: 20 },
            { category: "C", value: 30 },
            { category: "D", value: 40 },
            { category: "E", value: 50 }
        ];

        // 创建画布
        var margin = { top: 20, right: 20, bottom: 20, left: 20 };
        var width = 500 - margin.left - margin.right;
        var height = 400 - margin.top - margin.bottom;

        var svg = d3.select("#barchart")
                    .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 xScale = d3.scaleBand()
                        .domain(data.map(function(d) { return d.category; }))
                        .range([0, width])
                        .padding(0.1);

        var yScale = d3.scaleLinear()
                        .domain([0, 50])
                        .range([height, 0]);

        // 绘制条形图
        svg.selectAll(".bar")
            .data(data)
            .enter()
            .append("rect")
            .attr("class", "bar")
            .attr("x", function(d) { return xScale(d.category); })
            .attr("y", function(d) { return yScale(d.value); })
            .attr("width", xScale.bandwidth())
            .attr("height", function(d) { return height - yScale(d.value); });
    </script>
</body>
</html>

六、D3.js 的实战应用

6.1 创建一个力导向图

力导向图是用于显示图形之间的连通性的一种图表类型。下面是一个用 D3.js 创建力导向图的示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>Force-directed Graph Example</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <div id="forcedirected"></div>
    <script>
        // 定义数据
        var nodes = [
            { id: "A", group: 1 },
            { id: "B", group: 1 },
            { id: "C", group: 2 },
            { id: "D", group: 2 },
            { id: "E", group: 3 },
            { id: "F", group: 3 }
        ];

        var links = [
            { source: "A", target: "B" },
            { source: "B", target: "C" },
            { source: "C", target: "D" },
            { source: "D", target: "E" },
            { source: "E", target: "F" }
        ];

        // 创建画布
        var width = 500;
        var height = 400;

        var svg = d3.select("#forcedirected")
                    .append("svg")
                    .attr("width", width)
                    .attr("height", height);

        // 创建力导向布局
        var simulation = d3.forceSimulation(nodes)
                            .force("link", d3.forceLink(links))
                            .force("charge", d3.forceManyBody().strength(-100))
                            .force("center", d3.forceCenter(width / 2, height / 2))
                            .on("tick", ticked);

        // 绘制连线
        var link = svg.selectAll(".link")
                        .data(links)
                        .enter()
                        .append("line")
                        .attr("class", "link");

        // 绘制节点
        var node = svg.selectAll(".node")
                        .data(nodes)
                        .enter()
                        .append("circle")
                        .attr("class", "node")
                        .attr("r", 10)
                        .attr("fill", function(d) { return d.group === 1 ? "red" : d.group === 2 ? "blue" : "green"; })
                        .call(drag(simulation));

        // 节点拖动事件
        function drag(simulation) {

            function dragstarted(d) {
                if (!d3.event.active) simulation.alphaTarget(0.3).restart();
                d.fx = d.x;
                d.fy = d.y;
            }

            function dragged(d) {
                d.fx = d3.event.x;
                d.fy = d3.event.y;
            }

            function dragended(d) {
                if (!d3.event.active) simulation.alphaTarget(0);
                d.fx = null;
                d.fy = null;
            }

            return d3.drag()
                    .on("start", dragstarted)
                    .on("drag", dragged)
                    .on("end", dragended);
        }

        // 动态更新节点位置
        function ticked() {
            link.attr("x1", function(d) { return d.source.x; })
                .attr("y1", function(d) { return d.source.y; })
                .attr("x2", function(d) { return d.target.x; })
                .attr("y2", function(d) { return d.target.y; });

            node.attr("cx", function(d) { return d.x; })
                .attr("cy", function(d) { return d.y; });
        }
    </script>
</body>
</html>

6.2 创建一个堆叠条形图

堆叠条形图是一种用于比较多个类别数据之间差异的一种图表类型,以及多个类别数据在整体中的比例。下面是一个用 D3.js 创建堆叠条形图的示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>Stacked Bar Chart Example</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
    <div id="stackedbarchart"></div>
    <script>
        // 定义数据
        var data = [
            { category: "A", value1: 10, value2: 20, value3: 30 },
            { category: "B", value1: 20, value2: 30, value3: 40 },
            { category: "C", value1: 30, value2: 40, value3: 50 },
            { category: "D", value1: 40, value2: 50, value3: 60 },
            { category: "E", value1: 50, value2: 60, value3: 70 }
        ];

        // 创建画布
        var width = 500;
        var height = 400;

        var svg = d3.select("#stackedbarchart")
                    .append("svg")
                    .attr("width", width)
                    .attr("height", height);

        // 创建比例尺和堆叠布局
        var xScale = d3.scaleBand()
                        .domain(data.map(function(d) { return d.category; }))
                        .range([0, width])
                        .padding(0.1);

        var yScale = d3.scaleLinear()
                        .domain([0, 150])
                        .range([height, 0]);

        var stack = d3.stack()
                        .keys(["value1", "value2", "value3"])
                        .order(d3.stackOrderNone)
                        .offset(d3.stackOffsetNone);

        // 绘制条形图
        var series = stack(data);

        svg.selectAll(".serie")
            .data(series)
            .enter()
            .append("g")
                .attr("class", "serie")
                .attr("fill", function(d) { return d.key === "value1" ? "#e41a1c" : d.key === "value2" ? "#377eb8" : "#4daf4a"; })
            .selectAll("rect")
            .data(function(d) { return d; })
            .enter()
            .append("rect")
                .attr("x", function(d) { return xScale(d.data.category); })
                .attr("y", function(d) { return yScale(d[1]); })
                .attr("height", function(d) { return yScale(d[0]) - yScale(d[1]); })
                .attr("width", xScale.bandwidth());
    </script>
</body>
</html>

七、Plotly 的实战应用

7.1 创建一个交互式散点图

交互式散点图可以让用户接触数据背后的细节,并探索与特定数据点相关的详细信息。下面是一个使用 Plotly 创建交互式散点图的示例代码:

<!DOCTYPE html>
<html>
<head>
    <title>Scatter Plot Example</title>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
</head>
<body>
    <div id="scatterplot"></div>
    <script>
        // 定义数据
        var data = [
            { x: [1, 2, 3, 4, 5], y: [10, 20, 30, 40, 50], text: ["A", "B", "C", "D", "E"] }
        ];

        // 定义布局和选项
        var layout = {
            title: "Scatter Plot Example",
            xaxis: { title: "X-axis" },
            yaxis: { title: "Y-axis" },
            hovermode: "closest"
        };

        var options = {
            modeBarButtonsToRemove: ["toImage", "toggleSpikelines", "sendDataToCloud"]
        };
		</script>
 </body>

八、总结

掌握数据可视化需要多方面的努力和实践,但这些库提供了许多强大的工具,可以帮助您快速地创建交互式可视化。从基础开始,逐步学习 JavaScript、D3.js 和 Plotly,并通过练习项目来提高自己的技能。