0 fill null values with d3 series data
Asked Answered
B

1

6

I'm working on a multi-line chart in D3 but am having some issues with the rendering. I'm trying to render two lines with data that looks like this:

[
    { key:"line 1",  values: [ {x:1, y:1}, {x:2, y:2} ] },
    { key:"line 2" , values: [ {x:1, y:1}, {x:2, y:2}, {x:3, y:3} ] }
]

"line 2" renders just fine, but "line 1" stops rendering at x = 2. I understand that my dataset might be considered incomplete, but I was curious if there is a way to set a default value of 0 where there are gaps or null values for x? Specifically in this example I want "line 1" to display y=0 where x=3.

Bini answered 11/6, 2013 at 21:17 Comment(5)
This isn't something that JS would do, but the nvd3.js API may include a setting to enable this. It is possible to write some JavaScript that would insert the third element, but I would check the nvd3 API for a setting first.Andorra
(You haven't told us what you're using to draw your lines). If you're using d3's d3.svg.line() function to draw the paths then certainly there's no built-in way to tell it to draw more points than there are elements in the array. It does have a defined() method, which could come into play here, but you'd have to fill your array with those "undefined" elements beforehand. I also doubt that nvd3 has anything to handle this, but haven't checked.Felix
@AndrewGibson, I currently have a programatic approach to fill in the null data point but was hoping for a setting or function i could use from the D3 API like you suggested. Still have yet to find it...Bini
Like meetamit I'm now doubting that nvd3 has this setting, but it is something I would have looked for. Good luck.Andorra
@DanRamos You're on the right path. NVD3, and D3, don't have the ability to 'fill in' missing values because it can't possibly know what values are missing, but they have connivence functions that help you get the values. misoproject.com/dataset also have some nice utilities for manipulating data in the client.Jessejessee
J
2

D3 and NVD3 don't have a function to do this. Your best bet is to insert your missing values. Some CoffeeScript that uses some Underscore utilities, but d3 had many of the same functions, so you shouldn't need to necessarily depend on Underscore if you don't need it. First you get the list of domain values, then you insert your missing values.

The method getDomainValues takes data and a dimensions (a key) and pulls all the values to get the set of domain values. If you had data like:

   key : a
    values : [ {x: 4, y:1},  {x: 5, y:1}, {x: 7, y:1} ]
   key : b
    values : [ {x: 1, y:10}, {x: 2, y:5}, {x: 3, y:0} ]

It would return:

[1,2,3,4,5,7]


getDomainValues = (data, dimension) ->
 _.uniq _.flatten _.map data, (item) -> _.pluck(item.values, dimension)

The method insertValues inserts default values (most commonly 0) for dimension values not present in the values array. It sorts by dimension. If you had data like:

  key : a
    values : [ {x: 4, y:1},  {x: 2, y:1}, {x: 1, y:1} ]

And supplied a domain [0, 1,2,3,4,5] and a value of -10 you'd get:

  key : a
    values : [ {x: 0, y:-10}, {x: 1, y:1},  {x: 2, y:1}, {x: 3, y:-10}, {x: 4, y:1}, {x: 5, y: -10}]


insertValues = (data, value, dimension, metric, domain)->    
 defaults = {} 
 for item in domain
   v = {}
   v[dimension] = item
   v[metric] = value
   defaults[item] = v

 _.each data, (item) -> 
  vals = _.groupBy( item.values, (i) -> i[dimension])
  vals = _.flatten _.values _.defaults vals, defaults
  vals = _.sortBy vals, dimension 
  item.values = vals
 data

So you might call them like this:

data = [
    { key:"line 1",  values: [ {x:1, y:1}, {x:2, y:2} ] },
    { key:"line 2" , values: [ {x:1, y:1}, {x:2, y:2}, {x:3, y:3} ] }
]

domain = getDomainValues data, 'x'
filledData = insertValues data, 0, 'x', 'y', domain

See it in JavaScript: https://gist.github.com/FaKod/e6724675e4ebaf9f8fa4

Jessejessee answered 12/6, 2013 at 3:27 Comment(1)
"Compiled" insertValues(...) to JavaScript: gist.github.com/FaKod/e6724675e4ebaf9f8fa4Macguiness

© 2022 - 2024 — McMap. All rights reserved.