使用D3.js加载和解析多个csv文件 [英] Load and parse multiple csv files with D3.js

查看:1629
本文介绍了使用D3.js加载和解析多个csv文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用D3.js实现地图可视化。我有一些x csv文件(矩阵)。

I'm implementing a map visualization using D3.js. I have a number of x csv files (matrices). I want to load them and sum all values from all files.

我实现了一个for循环的名称数组,加载和解析数据使用 d3.text ,但由于异步行为,我找不到一个方法来做到这一点(我从<$ c $获得 undefined c> console.log ,然后是for循环的结果)。

I implemented a for loop over the array of names and load and parse the data using d3.text, but due to async behavior, I can't find a way to do this (I get undefined from console.log first and then the result of the for loop).

我试图使用async.js,但我不知道如何允许for循环的流。这是我的代码:

I've tried to use async.js but I cant figure out how to allow the flow of the for loop. Here is my code:

var total=[];
var matrix=[];

for(var i=0; i<filenames.length; i++){

    d3.text(filenames[i], function(text){
      matrix = d3.csv.parseRows(text).map(function (row){
        return row.map(function(value){ 
          return +value;
        });
      });
    });

    //sum the matrix pseudocode
    for(...){
      total = total + matrix;
    }
}

//here I need the sum of all files and then do other stuffs with the total:
console.log(total);
...
...

感谢。

推荐答案

我建议您使用递归函数。

I would suggest you do it with a recursive function.

在下面的示例中,您可以使用 d3.text() loadFilesAndCalculateSum() string它接受一个字符串数组,回调函数获取计算的sum而不是文件的文本。

In the following example you can use loadFilesAndCalculateSum() like the d3.text() but instead of one string it takes an array of strings and the callback gets the calculated sum instead of the text of a file.

/**
 * load all files and calculate the sum of the values
 * @param  {Array}    filenames Array with filenames as string
 * @param  {Function} cb        Callback function, gets the sum as param
 * @param  {number}   sum       The initial sum   
 * @param  {number}   i         Starting index for filenames
 * @return {void}
 */
function loadFilesAndCalculateSum(filenames, cb, sum, i) {
  sum = sum || 0;
  i = i || 0;
  d3.text(filenames[i], function(error, text) {
    //parse the rows and reduce them
    sum += d3.csv.parseRows(text).reduce(function(prev, curr) {
      //return previous sum + this rows sum
      return prev + d3.sum(curr, function(d){return +d;})
    },0); 

    if(i < filenames.length - 1){
      //load next file
      loadFilesAndCalculateSum(filenames, cb, sum, i+1);
    } else {
      //call the callback with the final sum
      cb(sum);
    }
  });
}

var filenames = ["file1.txt", "file2.txt", "file3.txt"];

loadFilesAndCalculateSum(filenames, function(sum){
  //do something with the total sum
  console.log(sum);
});

澄清这一点。你必须对回调函数中的sum进行处理,其中我把注释和总和做一些事情。此函数仍在执行异步。这意味着,在 loadFilesAndCalculateSum()函数之后写入的所有内容都可能在回调中的代码之前执行。您可以点击 在这里异步javascript 。 strong>

To clarify this. you have to do the processing of sum inside of the callback function where I put the comment do something with the total sum. This function is still executing async. That means, that everything you write after the loadFilesAndCalculateSum() function will possibly execute before the code inside the callback. You can find a little longer introduction to async javascript here

//this is executed first
//....
loadFilesAndCalculateSum(filenames, function(sum){
  //do something with the total sum
  //this is executed third, when all files are loaded and the sum is calculated
  console.log(sum);
});

//code after this point is executed second, while the files are being loaded.

如果你已经有一个函数与sum做一些事情,你可以传递这个函数到 loadFilesAndCalculateSum 作为第二个参数。这是可能的,因为功能是所谓的 一流公民

If you already have a function that does something with the sum, you can pass this function to the loadFilesAndCalculateSum as second parameter. This is possible because functions are so called first class citizens:

var addthis = 5;

function doSomethingWithTheSum(sum) {
  //everything you want to do with the sum goes inside this function.

  //from here you could call other functions and pass the sum.
  soSomethingDifferentWithTheSum(sum);

  //or you use the sum inside this function
  console.log(sum);
  var newsum = sum + addthis;
  console.log(sum);

  d3.select("whatever")
      .data([sum])
      .enter()
    .append("text")
      .text(function(d){ return d;});
}

loadFilesAndCalculateSum(filenames, doSomethingWithTheSum);

您可以像任何其他变量一样传递函数。在第一个例子中,我调用 loadFiles ... 函数 cb 的第二个参数, code> callback 。如doc注释中所述,此参数应为 Function 类型。

You can pass functions just like any other variable. in the first example I called the second parameter of the loadFiles... function cb which is the usual abbreviation for callback. As stated in the doc comment, this param should be of type Function.

loadFiles ... 函数的末尾,回调函数被

In the end of the loadFiles... function I the callback function gets called by

....
//call the callback with the final sum
cb(sum);
....

这里的和作为第一个参数赋给回调函数。因此,如果你传递一个函数,它应该使用一个参数,如第一个例子中的匿名函数或上面例子中的 doSomethingWithTheSum 函数。

Here the sum is given to the callback function as first parameter. Therefore if you pass a function, it should take a single param, like the anonymous function in the first example or the doSomethingWithTheSum function in the example above.

这篇关于使用D3.js加载和解析多个csv文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆