Dimensional Values and Faceting

In this document we will be building an intuition on what faceting is and how dimensional values play an important role in the process.

Data

We will be taking cars.csv as sample data source for illustration.

Simple chart to faceted visualization

Let's see what happens conceptually if we want to create a simple bar graph from this data. We plot the field Origin in x axis and Horsepower in y axis.

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.

let env = muze(); 
// Create an instance of canvas which houses the visualization
let canvas = env.canvas();

canvas
  	.rows(['Horsepower']) // Acceleration goes in Y-Axis
  	.columns(['Origin']) // Cylinders goes in X-Axis
  	.width(650)
  	.height(400)
  	.data(dm) //  Feed data
  	.mount('#chart-container'); // Render on the DOM el

When we pass data to canvas, it does not takes the data as is for rendering. Canvas performs a group by operation with all the dimensions present in the encoding channels (rows, columns, color, shape, size). In this case two fields are assigned to rows and columns, due to which the data gets transformed to the following form for rendering. Out of these two fields, one field is dimension which is used to perform the groupBy operation.

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.
  
const outputDM = dm.groupBy(['Origin'], {});

In this example canvas applies groupBy operation using Origin dimension. As you can see the resultant instance of DataModel contains only the unique values of the dimension(i.e., Origin). The values of the measure fields get aggregated when groupBy happens. Every unique value of a dimension is called dimensional value.

Now when we add another dimension in columns, and we get the following visualization.

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.
  
const env = muze(); 
const canvas = env.canvas();

canvas
  	.rows(['Horsepower']) // Acceleration goes in Y-Axis
	.columns(['Cylinders','Origin']) // Cylinders goes in X-Axis
  	.minUnitHeight(10)	
  	.minUnitHeight(10)		
  	.width(1000)
  	.height(400)
  	.data(dm) //  Feed data
  	.mount('#chart-container'); // Render on the DOM el
});

Let’s pause and think about how this visualization is created from the code before reading any further.

Just like last example, canvas applies group by operator with all the two dimensions (out of three fields) mentioned in the encoding channels, and the data gets transformed to the following form.

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.
  
const outputDM = dm.groupBy(['Cylinders', 'Origin'], {});

The fields Origin and Horsepower are used to create the axes while the field Cylinders is used to create the facets. Just like Origin and Horsepower were repeated for all of the Cylinders in the above instance of DataModel, a unit of visualization is repeated for all the dimensional values of Cylinders.

The above example was a use case of column faceting. If you provide more than one variable in rows then row faceting happens.

And thats the simple concept of faceting.

logo

Check out

Do rename rows to columns and columns to rows to checkout the effect.

Facets

Muze mandatorily needs X and Y axis to create a visualization (with cartesian coordinate). This information is passed through rows and columns. Muze creates a unit chart with this information. If more than one dimension is present in rows and columns, Muze repeats that unit visulization for all dimensional values of the newly added dimension , which was not used to create axes.

For example, consider that we have the distribution of Horsepower for each value in Cylinders. This way we get to know what is the average Horsepower generated by each Cylinders. But, what if we wanted to know the average Horsepower per Cylinders of the cars coming out of every country (Origin).

We will need to draw multiple charts for each combination of Origin and Cylinders. Muze can do that for you. All you have to do is give the encodings in right order.

This creates three separate bar charts as shown below:

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.

const env = muze();
const canvas = env.canvas();
canvas
  	.data(dm)
  	.width(500)
  	.height(800)
  	.rows(['Origin', 'Cylinders'])
  	.columns(['Horsepower']) /* Year is a temporal field */
  	.mount('#chart-container');

We have faceted our chart by Origin and as such we get a row for each unique facet.

Scaling the last example, we might want to see this visualization with a different facet. For instance, we could facet the visualization based on the Year of manufacturing of a car.

main
run-button
run-button
reset-button
// DataModel instance is created from https://www.charts.com/static/cars.json data,
// https://www.charts.com/static/cars-schema.json schema and assigned to variable dm.
  
const env = muze();
const canvas = env.canvas();

canvas
  	.data(dm)
  	.minUnitHeight(30)
  	.minUnitWidth(10)
  	.width(1200)
  	.height(400)
  	.rows(['Origin', 'Cylinders'])
  	.columns(['Year', 'Horsepower']) /* Year is a temporal field */
  	.mount('#chart-container') /* Attaching the canvas to DOM element */

So what exactly do we mean by Faceting?

In a faceted classification system, each information element is classified along multiple explicit dimensions, called facets. This enables the classifications to be accessed and ordered in multiple ways rather than in any one single way.

In Muze, faceting is spawning instance of DataModel corresponding to a dimensional values of a particular dimension.

Therefore, in the earlier example, when we facet the DataModel with the respective rows and column fields, Muze is essentially creating multiple faceted DataModels with each combination of facet and based on the visual encoding applied to it, it gets transformed to respective chart.

How Muze establishes Faceting?

First, we facet the original DataModel with a particular dimension. We get the faceted set of instances of DataModels corresponding to each dimensional value of the dimension.

Facet flow 1

For instance, If we have three Origin values as European Union, USA and Japan in the original DataModel, we will get three DataModels, each of which has the set of fields corresponding to the particular Origin:

Facet flow 2

Similarly, for multiple sets of facets, we get multiple layers of faceted models, for example a faceting with Origin and Cylinders:

Facet flow 3

The above row faceting achieves in providing rows for each of the facet combinations.

Thereafter, we can add column facets to further expand the faceting. Consider that we need to see how the distribution for Horsepower gets affected per Cylinders for every Origin and Year

First we facet all the DataModels row-wise and then, each of the rows gets further faceted for each Year Value in the column. Here's how the above process takes place:

Facet flow 4

By faceting, we can compose a whole set of visualizations based on the values in the DataModel and we can control the direction of faceting.

Wrapping Up

We now have a fair idea of what faceting does. It divides a particular DataModel into a set of DataModels which can be consumed by Muze to make several visualizations. These DataModels are obtained based on different dimensional values of different sets of dimensions, each of which can be represented as a visualization by applying the appropriate visual encodings to it. Also, we learnt that Muze provides us two ways of faceting, row-wise and column-wise and we can combine the two to create powerful visualizations.

Next we are going to learn about retinal encodings.