Easynow
Easynow

Reputation: 201

D3 nested array, extracting non key column

I'm trying to create a multi series line plot with D3 based on nested data (key variable of subgrp). I would like the colour of the stroke line to be determined by a non-key field (grp), but I can't access the value.

I've managed to achieve this using a none D3 approach (appending subgrp and grp and using this as the key), but there must be a more compliant way of doing it. I've looked at a number of similar questions/ tutorial, but haven't been able to get them to work.

A simplified version of the code is below.

Thanks in advance.

<!DOCTYPE html>
<html lang="en">
<head>

  <script src="https://d3js.org/d3.v5.min.js"></script>
<body>


<script>

//build the data array
var dataset = [
     {"yval": 1,"xval": 4,"grp":"a",subgroup:"sg1"}
    ,{"yval": 10,"xval": 20,"grp":"a",subgroup:"sg1"}
     ,{"yval": 30,"xval": 30,"grp":"a",subgroup:"sg2"}
    ,{"yval": 40,"xval": 10,"grp":"a",subgroup:"sg2"}
     ,{"yval": 10,"xval": 30,"grp":"b",subgroup:"sg3"}
    ,{"yval": 30,"xval": 40,"grp":"b",subgroup:"sg3"}	
     ,{"yval": 0.4,"xval": 10,"grp":"b",subgroup:"sg4"}
    ,{"yval": 50,"xval": 90,"grp":"b",subgroup:"sg4"}		
	
	]

//nest the data on the subgroup 
var dataNest = d3.nest()
        .key(function(d) {return d.subgroup;})
        .entries(dataset);

//line generator
var line = d3.line()
    .x(function(d) { return d.xval; }) 
    .y(function(d) { return d.yval; }) 
	
//add an svg element
svg=d3.select("body")
  .append("svg");
 

 //for each subgroup plot a distinct line
dataNest.forEach(function(d,i) { 
        svg.append("path")
            .attr("d", line(d.values))
			.style("stroke","red")
            //style colour should be driven by an if clause based on the grp field
			});
   
   
   
</script>
</html>

Upvotes: 1

Views: 71

Answers (1)

rioV8
rioV8

Reputation: 28713

Just access the field you want

.style("stroke", e => d.values[0].grp == "a" ? "red" : "blue")

<!DOCTYPE html>
<html lang="en">
<head>

  <script src="https://d3js.org/d3.v5.min.js"></script>
<body>


<script>

//build the data array
var dataset = [
     {"yval": 1,"xval": 4,"grp":"a",subgroup:"sg1"}
    ,{"yval": 10,"xval": 20,"grp":"a",subgroup:"sg1"}
     ,{"yval": 30,"xval": 30,"grp":"a",subgroup:"sg2"}
    ,{"yval": 40,"xval": 10,"grp":"a",subgroup:"sg2"}
     ,{"yval": 10,"xval": 30,"grp":"b",subgroup:"sg3"}
    ,{"yval": 30,"xval": 40,"grp":"b",subgroup:"sg3"}	
     ,{"yval": 0.4,"xval": 10,"grp":"b",subgroup:"sg4"}
    ,{"yval": 50,"xval": 90,"grp":"b",subgroup:"sg4"}		
	
	]

//nest the data on the subgroup 
var dataNest = d3.nest()
        .key(function(d) {return d.subgroup;})
        .entries(dataset);

//line generator
var line = d3.line()
    .x(function(d) { return d.xval; }) 
    .y(function(d) { return d.yval; }) 
	
//add an svg element
svg=d3.select("body")
  .append("svg");
 
//for each subgroup plot a distinct line
dataNest.forEach(function(d,i) { 
        svg.append("path")
            .attr("d", line(d.values))
			.style("stroke", e => d.values[0].grp == "a" ? "red" : "blue")
            //style colour should be driven by an if clause based on the grp field
			});
   
   
   
</script>
</html>

Upvotes: 3

Related Questions