将 D3.csv 修改为小写列名的正确方法

right way to modify d3.csv to lower case column names

本文关键字:方法 csv D3 修改      更新时间:2023-09-26

有一个处理客户端提供的csv数据文件的应用程序。 Javascript 区分大小写。但是大多数统计信息包不区分大小写,因此列名称具有各种大小写。 此外,如果它们通过 SAS、SPSS 或其他程序运行文件并另存为新文件,将所有内容转换为大写或小写,则大小写可能会更改。

所以我修改了 D3,使其自动将列名转换为小写。 这可以通过修改d3.js源代码来添加.toLocaleUpperCase(),如下所示:

    ...
    dsv.parse = function(text, f) {
      var o;
      return dsv.parseRows(text, function(row, i) {
        if (o) return o(row, i - 1);
        var a = new Function("d", "return {" + row.map(function(name, i) {
          return JSON.stringify(name.toLocaleUpperCase()) + ": d[" + i + "]";
        }).join(",") + "}");
        o = f ? function(row, i) {
          return f(a(row), i);
        } : a;
      });
    };
    ...

唯一的小挑战是我不能只是将其作为小猴子补丁或插件添加到我的代码中。 导入d3.dsv时调用此代码块,这取决于d3_xhr定义,这需要d3.xhr等。 所以我下载了整个d3.js并如上所述对其进行修改,并另存为d3.mod.js.

可以想象,当我们需要更新 d3 时,这会在一两年内咬我或其他开发人员。 处理这样的模组的正确方法是什么™?

可以使用 d3.csv 接受的accessor来指定行数据的转换方式。

下面的函数接受一个对象并将其所有属性转换为小写。该示例使用 d3.csv.parse() 而不是 d3.csv(),因为在这里演示更直接,但您可以使用 d3.csv() 做同样的事情。

不幸的是,此函数在每一行中被调用,而不是在行标题中读取时调用一次。也许有更好的方法...

var string = "Year,Make,Model,Length'n" +
  "1997,Ford,E350,2.34'n" +
  "2000,Mercury,Cougar,2.38'n";
function convertPropsToLowerCase(d) {
  Object.keys(d).forEach(function(origProp) {
    var lowerCaseProp = origProp.toLocaleLowerCase();
    // if the uppercase and the original property name differ
    // save the value associated with the original prop
    // into the lowercase prop and delete the original one
    if (lowerCaseProp !== origProp) {
      d[lowerCaseProp] = d[origProp];
      delete d[origProp];
    }
  });
  return d;
}
var obj = d3.csv.parse(string, convertPropsToLowerCase);
console.log(JSON.stringify(obj,null, ''t'));
/*
[
	{
		"year": "1997",
		"make": "Ford",
		"model": "E350",
		"length": "2.34"
	},
	{
		"year": "2000",
		"make": "Mercury",
		"model": "Cougar",
		"length": "2.38"
	}
] 
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

在某些情况下,这可能会快得多。我通常会做的是防止逐个迭代和更改每个键。


let csvText = "year,make,model,length'n1997,Ford,E350,2.34'n2000,Murcury,Cougar,2.38'n"
//or - to convert your csv object into a string
// let csvText = d3.csvFormat(csvObject)
let csvRows = csvText.split("/n") //convert csv string into array of rows
let arrayOfColumnHeaders = csvRows[0].split(",") //get column names as array of strings
let newColumns = arrayOfColumnHeaders.map(column => column.toLowerCase()).join(",") //change them
csvRows[0]=newColumns //replace the headers with new ones
let newtext= csvRows.join("'n") // convert array of rows back into single string
let csvObject = d3.csvParse(newtext) //now parse it