Plotting the famous Iris flower dataset with R.

xy <- iris[,1:2]
class <- iris[,"Species"]

Initial plot, with default options, of the classic data set of measurements over three species of iris flowers is quite good already. Lets see if it can be improved.

plot(xy)

We kill the frames to increase data-ink ratio and replace labels with nicer version with information about the units (cm), which is an important bit of information.

plot(xy,bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)")

Could the frames be used to something useful? Lets add a rug plot.

plot(xy,bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)")
for(i in 1:2) rug(xy[,i],side=i)

There is a problem with overlap of points. One point in the visualisation can actually represent one or more points. Therefore, we add some random jitter to the data to make overlapping points separate visually.

rxy <- apply(xy,2,jitter)
plot(rxy,bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)")
for(i in 1:2) rug(rxy[,i],side=i)

Glyphs could be used to something useful instead to just show the xy-coordinates. Lets use them to tell the species of the flower. We use palette “Dark2” from http://colorbrewer2.org/#type=qualitative&scheme=Dark2&n=3. The colours in this palette are pre-attentively separable and they should be separable by most colour-blind persons as well.

rxy <- apply(xy,2,jitter)
## RColorBrewer gives handy and principled palettes of desired type
## require(RColorBrewer)
## col <- brewer.pal(3,"Dark2")
col <- c("#1B9E77","#D95F02","#7570B3")
plot(rxy,bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)",col=col[class])
for(i in 1:2) rug(rxy[,i],side=i)
legend("topleft",legend=levels(class),pch=1,col=col)

Lets use also other glyph options - here shape of the glyph - and make data points to pop out more strongly and move legend below the rug lines. Here we use color and shape to transmit the same species information. This way the display is usable also on black-white displays or photocopies, while colour may be the most efficient to separate the species on color-capable displays.

pch <- c(15,16,17)
plot(rxy,bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)",col=col[class],pch=pch[class])
legend("topleft",legend=levels(class),col=col,pch=pch)
for(i in 1:2) rug(rxy[,i],side=i)

Now the species are always drawn in the same order, setosa first, and virginica last. This leads to overlay patterns which may not reflect data (e.g., virginica tends to occlude versicolor etc.). To get rid of this effects lets do some randomization and randomize the order in which the glyphs are drawn.

p <- sample.int(dim(rxy)[1])
plot(rxy[p,],bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)",col=col[class[p]],pch=pch[class[p]])
legend("topleft",legend=levels(class),col=col,pch=pch)
for(i in 1:2) rug(rxy[,i],side=i)

Lets still use the ink of rug points to give information about the species.

plot(rxy[p,],bty="n",xlab="sepal length (cm)",ylab="sepal width (cm)",col=col[class[p]],pch=pch[class[p]])
legend("topleft",legend=levels(class),col=col,pch=pch)
for(i in 1:2) for(j in 1:3) rug(rxy[as.integer(class)==j,i],side=i,col=col[j])

We make the rug lines thicker to make them visually more distinct and to mitigate the effects of the difficulty of distincting colors drawn on small areas. Also, we re-order drawing so that there is no occlusion that would loose information, i.e., first draw legend, then the rug plots, and randomise the rug plot as well. We make the legend box gray to reduce chartjunk.

plot(rxy[p,],bty="n",type="n",xlab="sepal length (cm)",ylab="sepal width (cm)")
legend("topleft",legend=levels(class),box.col="gray",col=col,pch=pch) # bottom
for(i in 1:2) for(j in p) rug(rxy[j,i],side=i,col=col[class[j]],lwd=1) # middle, randomized
points(rxy[p,],col=col[class[p]],pch=pch[class[p]]) # top, randomized

LS0tCnRpdGxlOiAiSXJpcyBkYXRhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiAKUGxvdHRpbmcgdGhlIGZhbW91cyBbSXJpcyBmbG93ZXIgZGF0YXNldF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSXJpc19mbG93ZXJfZGF0YV9zZXQpIHdpdGggW1JdKGh0dHA6Ly93d3cuci1wcm9qZWN0Lm9yZy8pLiAgCgpgYGB7cn0KeHkgPC0gaXJpc1ssMToyXQpjbGFzcyA8LSBpcmlzWywiU3BlY2llcyJdCmBgYAoKSW5pdGlhbCBwbG90LCB3aXRoIGRlZmF1bHQgb3B0aW9ucywgb2YgdGhlIGNsYXNzaWMgZGF0YSBzZXQgb2YgbWVhc3VyZW1lbnRzIG92ZXIgdGhyZWUgc3BlY2llcyBvZiBpcmlzIGZsb3dlcnMgaXMgcXVpdGUgZ29vZCBhbHJlYWR5LiBMZXRzIHNlZSBpZiBpdCBjYW4gYmUgaW1wcm92ZWQuCgpgYGB7cn0KcGxvdCh4eSkKYGBgCgpXZSBraWxsIHRoZSBmcmFtZXMgdG8gaW5jcmVhc2UgZGF0YS1pbmsgcmF0aW8gYW5kIHJlcGxhY2UgbGFiZWxzIHdpdGggbmljZXIgdmVyc2lvbiB3aXRoIGluZm9ybWF0aW9uIGFib3V0IHRoZSB1bml0cyAoY20pLCB3aGljaCBpcyBhbiBpbXBvcnRhbnQgYml0IG9mIGluZm9ybWF0aW9uLgoKYGBge3J9CnBsb3QoeHksYnR5PSJuIix4bGFiPSJzZXBhbCBsZW5ndGggKGNtKSIseWxhYj0ic2VwYWwgd2lkdGggKGNtKSIpCmBgYAoKQ291bGQgdGhlIGZyYW1lcyBiZSB1c2VkIHRvIHNvbWV0aGluZyB1c2VmdWw/IExldHMgYWRkIGEgcnVnIHBsb3QuCgpgYGB7cn0KcGxvdCh4eSxidHk9Im4iLHhsYWI9InNlcGFsIGxlbmd0aCAoY20pIix5bGFiPSJzZXBhbCB3aWR0aCAoY20pIikKZm9yKGkgaW4gMToyKSBydWcoeHlbLGldLHNpZGU9aSkKYGBgCgpUaGVyZSBpcyBhIHByb2JsZW0gd2l0aCBvdmVybGFwIG9mIHBvaW50cy4gT25lIHBvaW50IGluIHRoZSB2aXN1YWxpc2F0aW9uIGNhbiBhY3R1YWxseSByZXByZXNlbnQgb25lIG9yIG1vcmUgcG9pbnRzLiBUaGVyZWZvcmUsIHdlIGFkZCBzb21lIHJhbmRvbSBqaXR0ZXIgdG8gdGhlIGRhdGEgdG8gbWFrZSBvdmVybGFwcGluZyBwb2ludHMgc2VwYXJhdGUgdmlzdWFsbHkuCgpgYGB7cn0Kcnh5IDwtIGFwcGx5KHh5LDIsaml0dGVyKQpwbG90KHJ4eSxidHk9Im4iLHhsYWI9InNlcGFsIGxlbmd0aCAoY20pIix5bGFiPSJzZXBhbCB3aWR0aCAoY20pIikKZm9yKGkgaW4gMToyKSBydWcocnh5WyxpXSxzaWRlPWkpCmBgYAoKR2x5cGhzIGNvdWxkIGJlIHVzZWQgdG8gc29tZXRoaW5nIHVzZWZ1bCBpbnN0ZWFkIHRvIGp1c3Qgc2hvdyB0aGUgeHktY29vcmRpbmF0ZXMuIExldHMgdXNlIHRoZW0gdG8gdGVsbCB0aGUgc3BlY2llcyBvZiB0aGUgZmxvd2VyLiBXZSB1c2UgcGFsZXR0ZSAiRGFyazIiIGZyb20gPGh0dHA6Ly9jb2xvcmJyZXdlcjIub3JnLyN0eXBlPXF1YWxpdGF0aXZlJnNjaGVtZT1EYXJrMiZuPTM+LiBUaGUgY29sb3VycyBpbiB0aGlzIHBhbGV0dGUgYXJlIHByZS1hdHRlbnRpdmVseSBzZXBhcmFibGUgYW5kIHRoZXkgc2hvdWxkIGJlIHNlcGFyYWJsZSBieSBtb3N0IGNvbG91ci1ibGluZCBwZXJzb25zIGFzIHdlbGwuCgpgYGB7cn0Kcnh5IDwtIGFwcGx5KHh5LDIsaml0dGVyKQojIyBSQ29sb3JCcmV3ZXIgZ2l2ZXMgaGFuZHkgYW5kIHByaW5jaXBsZWQgcGFsZXR0ZXMgb2YgZGVzaXJlZCB0eXBlCiMjIHJlcXVpcmUoUkNvbG9yQnJld2VyKQojIyBjb2wgPC0gYnJld2VyLnBhbCgzLCJEYXJrMiIpCmNvbCA8LSBjKCIjMUI5RTc3IiwiI0Q5NUYwMiIsIiM3NTcwQjMiKQpwbG90KHJ4eSxidHk9Im4iLHhsYWI9InNlcGFsIGxlbmd0aCAoY20pIix5bGFiPSJzZXBhbCB3aWR0aCAoY20pIixjb2w9Y29sW2NsYXNzXSkKZm9yKGkgaW4gMToyKSBydWcocnh5WyxpXSxzaWRlPWkpCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWxldmVscyhjbGFzcykscGNoPTEsY29sPWNvbCkKYGBgCgpMZXRzIHVzZSBhbHNvIG90aGVyIGdseXBoIG9wdGlvbnMgLSBoZXJlIHNoYXBlIG9mIHRoZSBnbHlwaCAtIGFuZCBtYWtlIGRhdGEgcG9pbnRzIHRvIHBvcCBvdXQgbW9yZSBzdHJvbmdseSBhbmQgbW92ZSBsZWdlbmQgYmVsb3cgdGhlIHJ1ZyBsaW5lcy4gSGVyZSB3ZSB1c2UgY29sb3IgYW5kIHNoYXBlIHRvIHRyYW5zbWl0IHRoZSBzYW1lIHNwZWNpZXMgaW5mb3JtYXRpb24uIFRoaXMgd2F5IHRoZSBkaXNwbGF5IGlzIHVzYWJsZSBhbHNvIG9uIGJsYWNrLXdoaXRlIGRpc3BsYXlzIG9yIHBob3RvY29waWVzLCB3aGlsZSBjb2xvdXIgbWF5IGJlIHRoZSBtb3N0IGVmZmljaWVudCB0byBzZXBhcmF0ZSB0aGUgc3BlY2llcyBvbiBjb2xvci1jYXBhYmxlIGRpc3BsYXlzLgoKCmBgYHtyfQpwY2ggPC0gYygxNSwxNiwxNykKcGxvdChyeHksYnR5PSJuIix4bGFiPSJzZXBhbCBsZW5ndGggKGNtKSIseWxhYj0ic2VwYWwgd2lkdGggKGNtKSIsY29sPWNvbFtjbGFzc10scGNoPXBjaFtjbGFzc10pCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWxldmVscyhjbGFzcyksY29sPWNvbCxwY2g9cGNoKQpmb3IoaSBpbiAxOjIpIHJ1ZyhyeHlbLGldLHNpZGU9aSkKYGBgCgpOb3cgdGhlIHNwZWNpZXMgYXJlIGFsd2F5cyBkcmF3biBpbiB0aGUgc2FtZSBvcmRlciwgc2V0b3NhIGZpcnN0LCBhbmQgdmlyZ2luaWNhIGxhc3QuIFRoaXMgbGVhZHMgdG8gb3ZlcmxheSBwYXR0ZXJucyB3aGljaCBtYXkgbm90IHJlZmxlY3QgZGF0YSAoZS5nLiwgdmlyZ2luaWNhIHRlbmRzIHRvIG9jY2x1ZGUgdmVyc2ljb2xvciBldGMuKS4gVG8gZ2V0IHJpZCBvZiB0aGlzIGVmZmVjdHMgbGV0cyBkbyBzb21lIHJhbmRvbWl6YXRpb24gYW5kIHJhbmRvbWl6ZSB0aGUgb3JkZXIgaW4gd2hpY2ggdGhlIGdseXBocyBhcmUgZHJhd24uCgpgYGB7cn0KcCA8LSBzYW1wbGUuaW50KGRpbShyeHkpWzFdKQpwbG90KHJ4eVtwLF0sYnR5PSJuIix4bGFiPSJzZXBhbCBsZW5ndGggKGNtKSIseWxhYj0ic2VwYWwgd2lkdGggKGNtKSIsY29sPWNvbFtjbGFzc1twXV0scGNoPXBjaFtjbGFzc1twXV0pCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWxldmVscyhjbGFzcyksY29sPWNvbCxwY2g9cGNoKQpmb3IoaSBpbiAxOjIpIHJ1ZyhyeHlbLGldLHNpZGU9aSkKYGBgCgpMZXRzIHN0aWxsIHVzZSB0aGUgaW5rIG9mIHJ1ZyBwb2ludHMgdG8gZ2l2ZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3BlY2llcy4KCmBgYHtyfQpwbG90KHJ4eVtwLF0sYnR5PSJuIix4bGFiPSJzZXBhbCBsZW5ndGggKGNtKSIseWxhYj0ic2VwYWwgd2lkdGggKGNtKSIsY29sPWNvbFtjbGFzc1twXV0scGNoPXBjaFtjbGFzc1twXV0pCmxlZ2VuZCgidG9wbGVmdCIsbGVnZW5kPWxldmVscyhjbGFzcyksY29sPWNvbCxwY2g9cGNoKQpmb3IoaSBpbiAxOjIpIGZvcihqIGluIDE6MykgcnVnKHJ4eVthcy5pbnRlZ2VyKGNsYXNzKT09aixpXSxzaWRlPWksY29sPWNvbFtqXSkKYGBgCgpXZSBtYWtlIHRoZSBydWcgbGluZXMgdGhpY2tlciB0byBtYWtlIHRoZW0gdmlzdWFsbHkgbW9yZSBkaXN0aW5jdCBhbmQgdG8gbWl0aWdhdGUgdGhlIGVmZmVjdHMgb2YgdGhlIGRpZmZpY3VsdHkgb2YgZGlzdGluY3RpbmcgY29sb3JzIGRyYXduIG9uIHNtYWxsIGFyZWFzLiBBbHNvLCB3ZSByZS1vcmRlciBkcmF3aW5nIHNvIHRoYXQgdGhlcmUgaXMgbm8gb2NjbHVzaW9uIHRoYXQgd291bGQgbG9vc2UgaW5mb3JtYXRpb24sIGkuZS4sIGZpcnN0IGRyYXcgbGVnZW5kLCB0aGVuIHRoZSBydWcgcGxvdHMsIGFuZCByYW5kb21pc2UgdGhlIHJ1ZyBwbG90IGFzIHdlbGwuIFdlIG1ha2UgdGhlIGxlZ2VuZCBib3ggZ3JheSB0byByZWR1Y2UgY2hhcnRqdW5rLgoKYGBge3J9CnBsb3Qocnh5W3AsXSxidHk9Im4iLHR5cGU9Im4iLHhsYWI9InNlcGFsIGxlbmd0aCAoY20pIix5bGFiPSJzZXBhbCB3aWR0aCAoY20pIikKbGVnZW5kKCJ0b3BsZWZ0IixsZWdlbmQ9bGV2ZWxzKGNsYXNzKSxib3guY29sPSJncmF5Iixjb2w9Y29sLHBjaD1wY2gpICMgYm90dG9tCmZvcihpIGluIDE6MikgZm9yKGogaW4gcCkgcnVnKHJ4eVtqLGldLHNpZGU9aSxjb2w9Y29sW2NsYXNzW2pdXSxsd2Q9MSkgIyBtaWRkbGUsIHJhbmRvbWl6ZWQKcG9pbnRzKHJ4eVtwLF0sY29sPWNvbFtjbGFzc1twXV0scGNoPXBjaFtjbGFzc1twXV0pICMgdG9wLCByYW5kb21pemVkCmBgYA==