Data to Viz in Four Steps
This week's learning objective is to become familiar with the basic four-step process of going from data to visualization.
- Load Data
- Template
- Map
- Populate
Study the following example carefully.
Step 1: Load Data
data.countries = [{name: 'China', pop: 1393783836},
{name: 'India', pop: 1267401849},
{name: 'USA', pop: 322583006},
{name: 'Indonesia', pop: 25281224}]
Step 2: Template
For each data point, think about how we want to visualize it. In particular, we define how to map a data attribute to a visual attribute. In this simplest example, we are mapping the order (i-th) data attribute to the x visual attribute of a rectangle.
template.foo
<rect x="${d.x}"
width="20"
height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
There is a special object template that holds user-defined template strings.
Note that a name of this particular template string is set to be foo. The
content of the string can be accessed by template.foo in a code block.
Step 3: Map
Next, for each data point, we want to map it to a viz object that defines the attribute values we like to populate the template with. In this simplest example, there's only one attribute, x.
function computeX(d, i) {
return i * 20
}
data.viz = _.map(data.countries, function(d, i){
return {
x: computeX(d, i)
}
})
We obtain the following array of data objects.
[
{
"x": 0
},
{
"x": 20
},
{
"x": 40
},
{
"x": 60
}
]
Step 4: Populate
The final step is to populate the template with the viz data calculated earlier.
// compile the template.foo into a template function
var compiled = _.template(template.foo)
var result = _.map(data.viz, function(d){
// invoke the compiled template function on each viz data
return compiled({d: d})
})
return result.join('\n')
The resulting svg tags are rendered as below
<rect x="0"
width="20"
height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="20"
width="20"
height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="40"
width="20"
height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="60"
width="20"
height="100"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
Your Turn
Now it is your turn. The following exercises are incomplete. Your learning task is to add code to complete each exercise.
Exercise 1. Use the height of each bar to represent population
Step 1: Import Data
data.countries = [{name: 'China', pop: 1393783836},
{name: 'India', pop: 1267401849},
{name: 'USA', pop: 322583006},
{name: 'Indonesia', pop: 25281224}]
Step 2: Define Mappers
function computeX(d, i) {
return i * 20
}
function computeHeight(d, i){
return d.pop/1000000
}
data.viz = _.map(data.countries, function(d, i){
return {
x: computeX(d, i),
height: computeHeight(d, i)
}
})
Step 3: Template
template.foo
<rect x="${d.x}"
width="20"
height="${d.height}"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
Step 4: Populate
// compile the template.foo into a template function
var compiled = _.template(template.foo)
var result = _.map(data.viz, function(d){
// invoke the compiled template function on each viz data
return compiled({d: d})
})
return result.join('\n')
The resulting svg tags are rendered as below
<rect x="0"
width="20"
height="1393.783836"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="20"
width="20"
height="1267.401849"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="40"
width="20"
height="322.583006"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="60"
width="20"
height="25.281224"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
Exercise 2. Use both the height and width of each bar to represent population
Step 1: Import Data
data.countries = [{name: 'China', pop: 1393783836},
{name: 'India', pop: 1267401849},
{name: 'USA', pop: 322583006},
{name: 'Indonesia', pop: 25281224}]
Step 2: Define Mappers
function computeX(d, i) {
return i * 200
}
function computeHeight(d, i){
return d.pop
Step 3: Template
template.foo
<rect x="${d.x}"
width="${d.width}"
height="${d.height}"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
Step 4: Populate
// compile the template.foo into a template function
var compiled = _.template(template.foo)
var result = _.map(data.viz, function(d){
// invoke the compiled template function on each viz data
return compiled({d: d})
})
return result.join('\n')
The resulting svg tags are rendered as below
<rect x="0"
width="200"
height="139.3783836"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="200"
width="200"
height="126.7401849"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="400"
width="200"
height="32.2583006"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<rect x="600"
width="20"
height="25.281224"
style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />