2013-10-16 26 views

回答

6

好,所以IRC人帮助我,并指着nest,伟大的工程(这是CoffeeScript的):

nested_data = d3.nest() 
    .key((d) -> d3.time.day(d.timestamp)) 
    .rollup((a) -> d3.sum(a, (d) -> d.amount)) 
    .entries(incoming_data) # An array of {timestamp: ..., amount: ...} objects 

# Optional 
nested_data.map (d) -> 
    d.date = new Date(d.key) 

这里的技巧是d3.time.day这需要一个时间戳,并告诉你这一天( 12点在夜间)时间戳属于。这个功能和其他的像d3.time.week等可以很好的保存时间序列。

另一个技巧是nest().rollup()函数,该函数按key()分组后,将给定day上的所有事件相加。

我想要的最后一件事就是在没有交易的日子里插入空值。这是代码的最后部分:

# Interpolate empty vals 
nested_data.sort((a, b) -> d3.descending(a.date, b.date)) 
ex = d3.extent(nested_data, (d) -> d.date) 
each_day = d3.time.days(ex[0], ex[1]) 

# Build a hashmap with the days we have 
data_hash = {} 
angular.forEach(data, (d) -> 
    data_hash[d.date] = d.values 
) 

# Build a new array for each day, including those where we didn't have transactions 
new_data = [] 
angular.forEach(each_day, (d) -> 
    val = 0 
    if data_hash[d] 
    val = data_hash[d] 
    new_data.push({date: d, values: val}) 
) 

final_data = new_data 

希望这有助于某人!

+0

帮帮我,谢谢! – John

1

直方图代码不支持这一点,但您可以自己轻松地进行分箱。假设你有每个交易的日期和计数,你可以像这样一天一天。

var bins = {}; 
transactions.forEach(function(t) { 
    var key = t.date.toDateString(); 
    bins[key] = bins[key] || 0; 
    bins[key] += t.amount; 
}); 

如果你需要的话,你显然可以把日期字符串解析回日期;在这里使用.toDateString()的要点是,时间部分被切断,并且每天所有事物都被分类。如果您想按另一个时间间隔分类,则可以使用相同的技巧并提取日期的不同部分。

+0

是的,这实际上是一种快速的方法。我可能会在这里使用'd3.time.day'而不是toDateString(),所以我可以很容易地使用'd3.time.week'切换到不同的bin大小。 – abourget