D3.js线图pandas dataframe JSON

时间:2017-11-02 16:50:17

标签: javascript python json d3.js

任何人都可以提供一个很好的例子,说明如何使用D3来解析python pandas数据帧to_json()的标准输出,最终看起来像这样:

"{"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4}}"

最终我正在寻找x轴上有时间的线图和y轴上'column1'的值

我已经设法使用不同的格式使用JSON数据:

{"2017-09-20T11:14:18.000Z","values":["column1":2.1,"column2":3.0]}

但理想情况下,我希望避免更改JSON的格式,因为它在其他地方使用。抱歉,如果我遗漏了一些明显的东西,我认为这样的例子会更容易找到!

1 个答案:

答案 0 :(得分:1)

最终,您可能希望将包含日期和值的对象或数组的数组传递给行生成器和缩放函数,这与d3.line()构造路径的方式最相符。

因此,虽然您不需要更改json的结构,但您需要提供绘制数据图表的脚本,但绘制数据图表的脚本需要创建具有更改结构的内容。

d3中经常需要这种数据结构,因此有许多d3辅助函数可以帮助完成此过程。考虑到您的示例数据框,在帮助绘制d3,d3.keys()d3.map()中的数据时会想到两个辅助函数:

  

d3.keys(object)<>

     

返回包含指定对象的属性名称的数组   (关联数组)。返回数组的顺序是未定义的。

而且,在d3.map()中,我们主要关注map.entries():

  

map.entries()<>

     

返回此映射中每个条目的键值对象数组。该   返回条目的顺序是任意的。每个条目的关键是a   string,但该值具有任意类型。

带上你的json:

{"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4}}

我们可以使用(我已经添加了第二列用于演示):

var df = {"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4},
"column2":{"2017-09-20T11:14:18.000Z":2.3,"2017-09-20T11:14:19.000Z":2.1,"2017-09-20T11:14:20.000Z":2.2}};
	
var dataSeries = d3.keys(df);  // get each column
var dataArray = [];            // the data array that we will plot
	
dataSeries.forEach(function(d) {
	dataArray.push(d3.map(df[d]).entries()); // get each key value pair and return as an object
	})
	
console.log(dataArray);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

这将输出包含每个系列的数组。每个系列都包含一个键值对的对象,我们可以用它来绘制数据。这将使数据相对直接地绘制图形,并且应该有更多使用此数据结构的示例也可以提供帮助。

请注意,此方法不要求每列具有相同数量的条目或相同的键(在这种情况下,相同的日期)。

使用此方法的简单图表可能如下所示:

var width = 500, height = 200;

////////////// structure data

var df = {"column1":{"2017-09-20T11:14:18.000Z":2.1,"2017-09-20T11:14:19.000Z":2.3,"2017-09-20T11:14:20.000Z":2.4},
"column2":{"2017-09-20T11:14:18.000Z":2.3,"2017-09-20T11:14:19.000Z":2.1,"2017-09-20T11:14:20.000Z":2.2}};
	
var dataSeries = d3.keys(df);
var dataArray = [];
	
dataSeries.forEach(function(d) {
	dataArray.push(d3.map(df[d]).entries()); // get each key value pair and return as an object
})

////////////// scale and draw data

var timeParse = d3.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
	
var x = d3.scaleTime()
	  .domain(d3.extent(dataArray[0], function(d) { return timeParse(d.key); }) )
	  .range([0,width]);
	  
	var y = d3.scaleLinear()
	  .domain(d3.extent(dataArray[0], function(d) { return d.value; }) )
	  .range([0,height])
	  
	var line = d3.line()
	  .x(function(d) {return x(timeParse(d.key)); })
	  .y(function(d) { return y(d.value); })
	  
	var svg = d3.select("body")
	  .append("svg")
	  .attr("width",width)
	  .attr("height",height);
	  
	svg.selectAll(null)
	  .data(dataArray)
	  .enter()
	  .append("path")
	  .attr("d",line)
	  .attr("stroke", function(d,i) { return ["steelblue","orange"][i]; })
	  .attr("stroke-width",2)
	  .attr("fill","none");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

注意我只根据数据框中的第一列来缩放数据