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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With