下面的代码来自https://github.com/emeeks/d3_in_action_2,特别是第4章,4_18.html。我的最小可复制示例也在下面。
问题:D3如何处理列标题中的非法字符?我无法让D3读取给定非法键的值。
示例数据文件的原始头看起来像这样:
day,tweets,retweets,favorite
然而,我的实际数据文件在头文件中有非法字符,即一个等号符号、一个空格字符和一个冒号,如下所示。注意,我不能更改数据文件。我能读,但不会写。
day,twe=ets,re tweets,fav:orite
这是我的测试数据文件,头中有非法字符:
day,twe=ets,re tweets,fav:orites
1,1,2,5
2,6,11,3
3,3,8,1
4,5,14,6
5,10,29,16
6,4,22,10
7,3,14,1
8,5,18,7
9,1,30,22
10,4,16,15
这是测试代码,根据Elijah Meeks的指示改编。注意<---SEE HERE---
行:
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js" type="text/JavaScript"></script>
<style>
path.domain {
stroke: none;
}
</style>
</head>
<body>
<div id="viz">
<svg style="width:600px;height:600px;" ></svg>
</div>
<script>
d3.csv("tweetdata2.csv", lineChart);
function lineChart(data) {
console.log(data);
xScale = d3.scaleLinear().domain([1,10.5]).range([20,480]);
yScale = d3.scaleLinear().domain([0,35]).range([480,20]);
xAxis = d3.axisBottom()
.scale(xScale)
.tickSize(480)
.tickValues([1,2,3,4,5,6,7,8,9,10]);
d3.select("svg").append("g").attr("id", "xAxisG").call(xAxis);
yAxis = d3.axisRight()
.scale(yScale)
.ticks(10)
.tickSize(480);
d3.select("svg").append("g").attr("id", "yAxisG").call(yAxis);
d3.select("svg").selectAll("circle.tweets")
.data(data)
.enter()
.append("circle")
.attr("class", "tweets")
.attr("r", 5)
.attr("cx", d => xScale(d.day))
.attr("cy", d => yScale(d.tweets)) // <-------SEE HERE-----
.style("fill", "#fe9a22");
//code commented out for brevity
}
</script>
</body>
</html>
我已经尝试了访问器函数的各种排列,大约8小时的工作价值,没有得到任何地方。下面是一个例子:
d3.csv("myData.csv", rowConverter, callBack);
function rowConverter(d)
{
console.log("in rowConverter");
//for (const property in d) {
// console.log(typeof(property));
// console.log(d.columns);
// console.log(`${property}: ${d[property]}`); }
d.day = parseInt(d.day),
d.tweets = parseInt(d.twe=eets),
d.retweets = parseInt(d.re tweets),
d.favorites = parseInt(d.fav:orites)
return d;
}
function callBack(d)
{
console.log(d);
// etc. omitted for brevity
}
我该如何处理?我该怎么办?谢谢。
CSV语法中没有规定这些字符是无效的。也就是说,您的CSV可以按原样使用:
const csv = `day,twe=ets,re tweets,fav:orites
1,1,2,5
2,6,11,3
3,3,8,1
4,5,14,6
5,10,29,16
6,4,22,10
7,3,14,1
8,5,18,7
9,1,30,22
10,4,16,15`;
const data = d3.csvParse(csv);
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
问题不在于这些字符在CSV中无效,这里的问题只是访问这些属性(如foo.twe=ets
中,这将不起作用)。在这种情况下,您可以简单地使用括号符号(如foo["twe=ets"]
):
const csv = `day,twe=ets,re tweets,fav:orites
1,1,2,5
2,6,11,3
3,3,8,1
4,5,14,6
5,10,29,16
6,4,22,10
7,3,14,1
8,5,18,7
9,1,30,22
10,4,16,15`;
const data = d3.csvParse(csv);
console.log(data[0]["twe=ets"]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
为了避免引用非法的列值,您可以只引用每个Object.values(d)
的数据点并将它们分配给您想要的列名
var url = "https://gist.githubusercontent.com/robinmackenzie/ff787ddb871cef050d7e6279991a0f07/raw/e59d34ef16b86d23b79dba13f8a778f1485d1c90/data.csv";
d3.csv(url, rowConverter, callBack);
function rowConverter(d, i) {
console.log("Converting row " + i);
var vals = Object.values(d); // <--- get the data ignoring object keys
return {
"days": parseInt(vals[0]), // <--- use the correct column names
"tweets": parseInt(vals[1]),
"retweets": parseInt(vals[2]),
"favorites": parseInt(vals[3])
};
}
function callBack(d) {
console.log("Data in callback");
console.log(d);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js"></script>
也许您想要删除行转换函数中列名的硬编码,如果是这样,您可以像下面这样提前定义它们:
var url = "https://gist.githubusercontent.com/robinmackenzie/ff787ddb871cef050d7e6279991a0f07/raw/e59d34ef16b86d23b79dba13f8a778f1485d1c90/data.csv";
var cols = ["days_xxx", "tweets_xxx", "retweets_xxx", "favorites_xxx"];
d3.csv(url, rowConverter, callBack);
function rowConverter(d, i) {
console.log("Converting row " + i);
var vals = Object.values(d); // <--- get the data ignoring object keys
var obj = {}
for ([ix, v] of vals.entries()) { // <--- get index and value of array of values
obj[cols[ix]] = +v; // <--- use the index to get the column name from array
}
console.log(obj);
return obj;
}
function callBack(d) {
console.log("Data in callback");
console.log(d);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js"></script>