javascript - 如何在 D3.js 中输入数组?

标签 javascript arrays d3.js graphics data-science

它有办法从 D3.js 中的数据集中输入整个数组吗?或者我必须在进入之前清理它吗?

我的数据集 .jason 的示例如下:

[
{
    "promoter": "Vigun01",
    "upstream": "[2, 57, 150, 376]"
},
{
    "promoter": "Vigun01",
    "upstream": "[500, 732, 765]"
},
{
    "promoter": "Vigun01",
    "upstream": "[675]"
},
{
    "promoter": "Vigun02",
    "upstream": "[623]"
},
{
    "promoter": "Vigun03",
    "upstream": "[133, 601]"
},
{
    "promoter": "Vigun04",
    "upstream": "[599, 650]"
},
{
    "promoter": "Vigun05",
    "upstream": "[50, 789]"
}
]

我在 D3.js 中的脚本在这里:

var svg = d3.select("#chart-area")
.append("svg")
    .attr("width", "400")
    .attr("height", "400");

d3.json("data/dataset.json").then(function(data){

data.forEach(d => {
    d.upstream = +d.upstream;
});
console.log(data);

var y = d3.scaleBand()
    .domain(data.map(function(d){
        return d.promoter;
    }))
    .range([0, 400])
    .paddingInner(0.2)
    .paddingOuter(0.2);

var x = d3.scaleLinear()
    .domain([0,1000])
    .range([0,400]);

var line = svg.selectAll("line")
    .data(data);

line.enter()
    .append('line')
        .attr('x1', 0)
        .attr('y1', (d,i)=>y(d.promoter))
        .attr('x2', 400)
        .attr('y2', (d,i)=>y(d.promoter))
        .attr('stroke-width', 1)
        .attr('stroke', 'black');


var circle = svg.selectAll("circle")
        .data(data)
    .enter()
        .append("circle")
        .attr("cy", function(d){
            return y(d.promoter)
        })
        .attr("cx", function(d){
           return x(d.upstream)
        })
        .attr("r", 5)
        .attr("fill", function(d) {
            return "black";
        });


}).catch(function(error){
    console.log(error)
});

我可以绘制单个输入,例如(“Vigun01”,“10”),但如果我有整个数组,则不能。

如果将 ("Vigun01", "[1,2,3,4]") 转换为许多输入,例如 ("Vigun01", "1"), ("Vigun01", "2"), ("Vigun01", "3"), ("Vigun01", "4") 但如何在数据集中执行此操作?

最佳答案

有几件事您需要调整:

  1. 首先,我建议您更改数据,使上游属性包含数组而不是字符串。我没有看到将它们作为字符串的好处,因此您应该在创建数据时更改它。

您的代码:

data.forEach(d => {
d.upstream = +d.upstream;
});

不会将字符串转换为数组或有意义的数字。它将产生 NaN。

  • 由于您想在一行上为外部 JSON 数组的每个元素绘制圆圈,但根据上游值数组值改变 x 位置,因此我建议将圆圈元素的创建分为两步。
  • 首先,为每个启动子创建一个 g 元素,如下所示:

    var circleGroups = svg.selectAll("g.circles")
      .data(data)
        .enter()
        .append("g")
        .attr("class", "circles"); 
    
  • 然后,为每个组元素创建与该启动子相对应的一组圆圈。为此,您必须稍微调整数据,然后以此进行数据连接。
  • 为同一启动子的圆圈创建新数组:

      function getCircleData(d) {
      var cdata = d.upstream.map (function(ele) { 
        return {upstream: ele, promoter: d.promoter};
      });
      return cdata; 
      }
    

    以及圆圈的数据连接:

        var circle = circleGroups.selectAll("circle")
            .data(getCircleData)
        .enter()
            .append("circle")
            .attr("cy", function(d){
                return y(d.promoter)
            })
            .attr("cx", function(d){
               return x(d.upstream)
            })
            .attr("r", 5)
            .attr("fill", function(d) {
                return "black";
            });
    

    这是完整的工作代码。我刚刚用在函数中设置数组来替换您的 AJAX 调用。

        var svg = d3.select("body").append("svg")
          .attr("width", 960)
          .attr("height", 500)
    
    // d3.json("data/dataset.json").then(function(data){
        let data = getData();
    
        /*
    data.forEach(d => {
        d.upstream = +d.upstream;
    });
    console.log(data);
    */
    
    var y = d3.scaleBand()
        .domain(data.map(function(d){
            return d.promoter;
        }))
        .range([0, 400])
        .paddingInner(0.2)
        .paddingOuter(0.2);
    
    var x = d3.scaleLinear()
        .domain([0,1000])
        .range([0,400]);
    
    var line = svg.selectAll("line")
        .data(data);
    
    line.enter()
        .append('line')
            .attr('x1', 0)
            .attr('y1', (d,i)=>y(d.promoter))
            .attr('x2', 400)
            .attr('y2', (d,i)=>y(d.promoter))
            .attr('stroke-width', 1)
            .attr('stroke', 'black');
    
    
        var circleGroups = svg.selectAll("g.circles")
          .data(data)
        	.enter()
        	.append("g")
        	.attr("class", "circles");
    
        var circle = circleGroups.selectAll("circle")
                .data(getCircleData)
            .enter()
                .append("circle")
                .attr("cy", function(d){
                    return y(d.promoter)
                })
                .attr("cx", function(d){
                   return x(d.upstream)
                })
                .attr("r", 5)
                .attr("fill", function(d) {
                    return "black";
                });
       
        function getCircleData(d) {
          var cdata = d.upstream.map (function(ele) { 
            return {upstream: ele, promoter: d.promoter};
          });
          return cdata; 
        }
        
        function getData() {
          var data = [
          {
              "promoter": "Vigun01",
              "upstream": [2, 57, 150, 376]
          },
          {
              "promoter": "Vigun01",
              "upstream": [500, 732, 765]
          },
          {
              "promoter": "Vigun01",
              "upstream": [675]
          },
          {
              "promoter": "Vigun02",
              "upstream": [623]
          },
          {
              "promoter": "Vigun03",
              "upstream": [133, 601]
          },
          {
              "promoter": "Vigun04",
              "upstream": [599, 650]
          },
          {
              "promoter": "Vigun05",
              "upstream": [50, 789]
          }
          ];
          return data;
        }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

    关于javascript - 如何在 D3.js 中输入数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55305098/

    相关文章:

    java - 二维数组,其单元格可以在索引处保存超过 1 个值

    javascript - D3 中的嵌套缩放问题

    svg - 如何在D3.js的强制布局中实现 "flying Arcs"作为链接

    javascript - Rails 手动调用特定的 js.rb

    javascript - AngularJS 没有更新?

    php - 在 PHP 和 Javascript 二维数组之间传输数据库数据

    javascript - D3 - 循环包装多个数据

    javascript - js 添加删除类

    javascript - Ajax 从浏览器上传文件到 FTP 服务器

    JavaScript - 保存、存储和更新数组