Function Repository Resource:

ChernoffFace

Source Notebook

Make Chernoff face diagrams

Contributed by: Anton Antonov

ResourceFunction["ChernoffFace"][vec]

makes a Chernoff face diagram for the numeric vector vec.

ResourceFunction["ChernoffFace"][asc]

makes a Chernoff face diagram for an Association asc of facial features to numeric values.

ResourceFunction["ChernoffFace"][matrix]

makes a list of Chernoff face diagrams corresponding to the rows of matrix.

ResourceFunction["ChernoffFace"][listOfAssociations]

makes a list of Chernoff face diagrams corresponding to the elements of listOfAssociations.

ResourceFunction["ChernoffFace"][data,opts]

makes Chernoff face diagrams using specified options opts.

Details and Options

ResourceFunction["ChernoffFace"] makes a Chernoff face diagram for a numeric vector or an association that maps facial features to numbers.
ResourceFunction["ChernoffFace"] works on lists of associations and lists of numeric vectors.
If the argument is a numeric matrix or a list of associations, the columns of the corresponding full array are rescaled first.
ResourceFunction["ChernoffFace"] takes all options of Graphics.
By default ResourceFunction["ChernoffFace"] makes black-and-white diagrams.
ResourceFunction["ChernoffFace"] diagrams are made with 17 face features.
The color function given to the option ColorFunction is used to auto-color the diagram.
The auto-coloring is done by associating colors with the keys "FaceColor", "IrisColor", "NoseColor", "MouthColor" and "EyeBallColor".
Here are the options taken by ResourceFunction["ChernoffFace"]:
ColorFunctionNone
"MakeSymmetric"Automatic
"RescaleRangeFunction"MinMax
Assume that ResourceFunction["ChernoffFace"] is given the argument vec and the specified color function is cf. If the argument vec has only one element, then:
"FaceColor"cf@vec[[1]]
If the argument vec has two elements, then:
"FaceColor"cf@vec[[1]]
"IrisColor"cf@vec[[2]]
If the argument vec has fewer than seven elements, then:
"FaceColor"cf@Mean@vec[[1;;2]]
"IrisColor"cf@Mean@vec[[3;;-1]]
If the argument vec has more than six elements, then:
"FaceColor"cf@Mean@vec[[1;;2]]
"MouthColor"cf@Mean@vec[[1;;3]]
"IrisColor"cf@Mean@vec[[4;;6]]
"NoseColor"cf@Mean@vec[[7;;-1]]
In all cases above, the automatic color assigned to "EyeBallColor" is White.

Examples

Basic Examples (1) 

Here is a Chernoff face diagram with a list of random numbers:

In[1]:=
SeedRandom[2]
ResourceFunction["ChernoffFace"][RandomReal[{0, 1}, 17]]
Out[2]=

Scope (11) 

Vector argument (2) 

Here is another Chernoff face constructed from random data:

In[3]:=
SeedRandom[232];
rvec = RandomReal[{-10, 10}, 12];
ResourceFunction["ChernoffFace"][rvec]
Out[5]=

If the length of the vector argument is larger than the number of facial features, only the first 17 elements are taken:

In[6]:=
SeedRandom[232];
rvec = RandomReal[{-10, 10}, 300];
ResourceFunction[
 "ChernoffFace"] /@ {rvec, Take[rvec, Length[ResourceFunction["ChernoffFace"]["FaceParts"]]]}
Out[8]=
In[9]:=
SeedRandom[232];
rvec = RandomReal[{0, 1}, 30];
ResourceFunction["ChernoffFace"][rvec]
Out[11]=

List of numeric vectors (2) 

Here is a random numeric matrix (a list of vectors):

In[12]:=
SeedRandom[23];
rmat = RandomVariate[SkewNormalDistribution[0, 3, 0.1], {25, 10}];

Visualize the random matrix with Chernoff face diagrams:

In[13]:=
Multicolumn[
 ResourceFunction["ChernoffFace"][rmat, ColorFunction -> "Rainbow", ImageSize -> 80], 5]
Out[13]=

Summary (1) 

Visualize a summary legend that helps the reading of the table of diagrams above:

In[14]:=
ResourceFunction["ChernoffFace"][rmat, "Summary", ColorFunction -> "Rainbow", ImageSize -> 80]
Out[14]=

Association of face parts to values (2) 

The main signature of ChernoffFace is using an association that specifies numerical values for different face parts of the diagram:

In[15]:=
ResourceFunction[
 "ChernoffFace"][<|"FaceLength" -> 0.9, "ForeheadShape" -> 0.3, "EyesVerticalPosition" -> 0.1, "EyeSize" -> 0.2, "EyeSlant" -> 1, "LeftEyebrowSlant" -> 0, "LeftIris" -> 0.9|>, ImageSize -> Small]
Out[15]=

The argument association can have specifications for the face part colors and face symmetry:

In[16]:=
ResourceFunction[
 "ChernoffFace"][<|"FaceLength" -> 0.9, "ForeheadShape" -> 0.3, "EyesVerticalPosition" -> 0.1, "EyeSize" -> 0.2, "EyeSlant" -> 1, "LeftEyebrowSlant" -> 0, "LeftIris" -> 0.9, "FaceColor" -> LightGreen, "IrisColor" -> Pink, "EyeBallColor" -> Yellow, "MakeSymmetric" -> False|>, ImageSize -> Small]
Out[16]=

The order of the face parts is based on research on which diagram features influence most influence how Chernoff face diagrams are perceived and comprehended.

Properties (3) 

Given the argument "Properties", a default association for making Chernoff face diagrams is retrieved:

In[17]:=
ResourceFunction["ChernoffFace"]["Properties"]
Out[17]=

Use "FaceParts" or "FacePartsProperties" to get an association with only the face parts:

In[18]:=
ResourceFunction["ChernoffFace"]["FacePartsProperties"]
Out[18]=

Here are the additional, non-numerical properties (face parts colors and symmetry):

In[19]:=
KeyComplement[{ResourceFunction["ChernoffFace"]["Properties"], ResourceFunction["ChernoffFace"]["FacePartsProperties"]}]
Out[19]=

List of associations (1) 

Here is a list of face-part-to-value associations:

In[20]:=
ascs = AssociationThread[
    Keys[ResourceFunction["ChernoffFace"]["FaceParts"][[
      2 ;; 8 ;; 2]]], #] & /@ rmat[[1 ;; 5, 1 ;; 4]]
Out[20]=
In[21]:=
ResourceFunction["ChernoffFace"][ascs]
Out[21]=

Options (9) 

ColorFunction (2) 

Using the option ColorFunction, we can produce different colorings:

In[22]:=
SeedRandom[15];
rvec = RandomReal[{0, 1}, 11];
# -> ResourceFunction["ChernoffFace"][rvec, ColorFunction -> #] & /@ {None, Automatic, "Pastel", ColorData["GrayTones"], ColorData["Rainbow"]}
Out[19]=

The option ColorFunction assigns automatic colors to argument's association keys:

In[23]:=
Flatten@StringCases[
  Keys@ResourceFunction["ChernoffFace"]["Properties"], __ ~~ "Color"]
Out[23]=

MakeSymmetric (3) 

The faces can be made symmetric for shorter records.

Here is a random numeric vector:

In[24]:=
SeedRandom[13];
rvec = RandomReal[{0, 1}, 8];

Here are diagrams produced with different values for the option "MakeSymmetric":

In[25]:=
ResourceFunction["ChernoffFace"][rvec, "MakeSymmetric" -> #, PlotLabel -> #] & /@ {Automatic, False, True}
Out[25]=

The option "MakeSymmetric" overrides the argument's association value of "MakeSymmetric":

In[26]:=
avec = AssociationThread[
  Take[Keys[ResourceFunction["ChernoffFace"]["FaceParts"]], Length[rvec]] -> rvec]
Out[26]=
In[27]:=
ResourceFunction["ChernoffFace"][
   Append[avec, "MakeSymmetric" -> True], "MakeSymmetric" -> #, PlotLabel -> #] & /@ {Automatic, False, True}
Out[27]=

RescaleRangeFunction (4) 

If the data argument is a numeric matrix or a list of associations with numeric values, then the data columns are rescaled to run between 0 and 1. The rescaling is done with Rescale using a data-range-finding function specified as a value to the option "RescaleRangeFunction" (the default of which is MinMax).

Here is a random numerical matrix:

In[28]:=
SeedRandom[18];
With[{m = 20, n = 8},
  rdata = Transpose[
    Table[RandomVariate[
      SkewNormalDistribution[RandomReal[{-10, 10}], RandomReal[{3, 10}], RandomReal[{0, 1}]], m], n]]
  ];

Here is a summary of the matrix:

In[29]:=
ResourceFunction["RecordsSummary"][rdata]
Out[29]=

Here is a list of Chernoff face diagrams produced with the default value for the option "RescaleRangeFunction":

In[30]:=
cf1 = ResourceFunction["ChernoffFace"][rdata, ImageSize -> 80, ColorFunction -> "Rainbow", "RescaleRangeFunction" -> MinMax]
Out[30]=

Here is a list of Chernoff face diagrams produced by making the ranges of the matrix columns slightly wider than they are:

In[31]:=
cf2 = ResourceFunction["ChernoffFace"][rdata, ImageSize -> 80, ColorFunction -> "Rainbow", "RescaleRangeFunction" -> ({-1, 1} + MinMax[#] &)]
Out[31]=

Applications (5) 

Visualizing the "EmployeeAttitude" dataset

In order to study a dataset with Chernoff face diagrams, we have to provide: (1) a list of Chernoff face diagrams; (2) a legend that shows how the face features are mapped to dataset's columns; and (3) a legend that shows Chernoff face diagrams for easy-to-understand instances of the dataset.

Get the "EmployeeAttitude" data:

In[32]:=
data = ExampleData[{"Statistics", "EmployeeAttitude"}];
Dimensions[data]
Out[21]=

Get the corresponding column names:

In[33]:=
dataColumnNames = ExampleData[{"Statistics", "EmployeeAttitude"}, "ColumnHeadings"]
Out[33]=

Here is a summary of the dataset:

In[34]:=
ResourceFunction["RecordsSummary"][data, dataColumnNames]
Out[34]=

Visualize with Chernoff faces:

In[35]:=
Legended[
 Grid[Partition[
   ResourceFunction["ChernoffFace"][data, ColorFunction -> "Rainbow", ImageSize -> 100], 6], Dividers -> All],
 Placed[Framed[
   Grid[Thread[{Take[
       Keys@ResourceFunction["ChernoffFace"]["FaceParts"], Length[dataColumnNames]], dataColumnNames}], Alignment -> {{Right, Left}}]], "Right"]]
Out[35]=

Make a table of records summary diagrams:

In[36]:=
Grid[Flatten@*List @@@ Normal[ResourceFunction["ChernoffFace"][data, "RecordsSummary", ImageSize -> 80, ColorFunction -> "Rainbow"]], Dividers -> All]
Out[36]=

We can see that: (1) higher learning is associated with higher ratings; (2) the higher the privileges, the higher the ratings. Other observations can also be made.

Properties and Relations (1) 

It is a good idea to compare the diagrams made with ChernoffFace to diagrams made with SectorChart:

In[37]:=
SeedRandom[1612]
rmat = Transpose@
   Table[RandomVariate[
     SkewNormalDistribution[RandomReal[{1, 10}], RandomReal[{1, 4}], RandomReal[{0.2, 0.8}]], 12], 5];
Multicolumn[
 Map[Row[{Image[
      ResourceFunction["ChernoffFace"][#, ColorFunction -> "Pastel"], ImageSize -> 80], Image[SectorChart[Transpose[{Range[Length[#]], #}], ChartLabels -> Placed[Range[Length[#]], "RadialOutside"]], ImageSize -> 120]}] &, Rescale /@ rmat], 4, Dividers -> All]
Out[33]=

Possible Issues (5) 

Record-wise vs. en bloc  (3) 

ChernoffFace invoked over an association or a list of numbers rescales the values of the argument data to run from 0 to 1 over the range Min[data]to Max[data]. ChernoffFace called on a list of associations or a matrix rescales the columns of the corresponding full array. Hence, in general, the diagrams produced by invoking ChernoffFace record-wise over a list of records are different from the diagrams produced by invoking ChernoffFace over the whole data set of records.

Here is a random numeric matrix (list of records):

In[38]:=
SeedRandom[18];
rdata = RandomReal[{-10, 10}, {10, 12}];

Here are Chernoff face diagrams made separately for each record:

In[39]:=
ResourceFunction["ChernoffFace"][#, ImageSize -> 80, ColorFunction -> "Rainbow"] & /@ rdata
Out[39]=

Here are Chernoff face diagrams made for the whole array:

In[40]:=
ResourceFunction["ChernoffFace"][rdata, ImageSize -> 80, ColorFunction -> "Rainbow"]
Out[40]=

We see that although the diagrams from the two lists are similar, they also have notable differences. With different data distributions, the differences will be greater or smaller.

Different perceptions with different color schemes (2) 

The same data visualized with different color schemes might make certain items or features more obscure or more prominent.

Using the "BrightBands" color scheme makes all diagrams to look unique:

In[41]:=
ResourceFunction["ChernoffFace"][rdata, ImageSize -> 80, ColorFunction -> "BrightBands"]
Out[41]=

Using the "WatermelonColors" color scheme over the same data makes the first and the last diagram to stand out:

In[42]:=
ResourceFunction["ChernoffFace"][rdata, ImageSize -> 80, ColorFunction -> "WatermelonColors"]
Out[42]=

Neat Examples (1) 

A table of random Chernoff faces:

In[43]:=
SeedRandom[7783];
Grid[Table[
  ResourceFunction["ChernoffFace"][
   ColorFunction -> RandomChoice[{"Rainbow", "BrightBands", "WatermelonColors", "TemperatureMap"}], "MakeSymmetric" -> RandomChoice[{True, False}], ImageSize -> Tiny], {6}, {6}]]
Out[42]=

Publisher

Anton Antonov

Version History

  • 1.0.0 – 20 November 2019

Source Metadata

Related Resources

Author Notes

The idea to use human faces in order to understand, evaluate, or easily discern (the records of) multidimensional data is very creative and inspirational. I personally find the use of Chernoff face diagrams useful in a small number of cases, but that is probably true for many "creative" data visualization methods.
A fundamental restriction of using Chernoff face diagrams is the necessity to properly transform the data variables into the ranges of the Chernoff face diagram parameters. Therefore, proper data transformation (standardizing and rescaling) is an inherent part of the application of Chernoff face diagrams.
The order of the face parts is based on some research which Chernoff face diagram features influence the most diagram’s comprehension. See the article cited in the Source Metadata section for more details.

License Information