8

I did a linear discriminant analysis using the function lda() from the package MASS. Now I would try to plot a biplot like in ade4 package (forLDA). Do you know how can I do this?

If I try to use the biplot() function it doesn't work. For example, if I use the Iris data and make LDA:

dis2 <- lda(as.matrix(iris[, 1:4]), iris$Species)

then I can plot it using the function plot(), but if I use the function biplot() it doesn't work:

biplot(dis2)
Error in nrow(y) : argument "y" is missing, with no default

How can I plot the arrows of variables?

gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
alexmulo
  • 751
  • 4
  • 11
  • 23

3 Answers3

4

I wrote the following function to do this:

lda.arrows <- function(x, myscale = 1, tex = 0.75, choices = c(1,2), ...){
  ## adds `biplot` arrows to an lda using the discriminant function values
  heads <- coef(x)
  arrows(x0 = 0, y0 = 0, 
         x1 = myscale * heads[,choices[1]], 
         y1 = myscale * heads[,choices[2]], ...)
  text(myscale * heads[,choices], labels = row.names(heads), 
    cex = tex)
}

For your example:

dis2 <- lda(as.matrix(iris[, 1:4]), iris$Species)
plot(dis2, asp = 1)
lda.arrows(dis2, col = 2, myscale = 2)

The length of the arrows is arbitrary relative to the lda plot (but not to each other, of course!). If you want longer or shorter arrows, change the value of myscale accordingly. By default, this plots arrows for the first and second axes. If you want to plot other axes, change choices to reflect this.

Tyler
  • 9,872
  • 2
  • 33
  • 57
  • @alexmulo : if you find an answer helpful, it's customary to give it an upvote. You can also indicate which answer best solves your problem by clicking the 'accept answer' checkmark. – Tyler Jun 27 '13 at 16:46
  • I am commenting this useful answer after many years coz I have found the code very handy and fit to my purposes, but cannot find a way (in base R) to change to arrows' head style. I would like to have smaller heads. I would not mind to get totally rid of the head. I did some web search but could not find a viable option. I used parameters such as 'code' or 'lend' with no avail. – NewAtGis Apr 09 '21 at 10:34
  • 1
    @NewAtGis use `arrows(... , length = 0.1, angle = 20)`. The length argument sets the length of the arrow head sides, and the angle argument controls the angle between the head and the shaft of the arrow. – Tyler Apr 09 '21 at 13:51
  • Extremely useful. But do you think there is an easy way to adjust your function's code in order for the arrows' length to be automatically scaled so that the length of the longest arrow does not pass the limits of the plotting area? – NewAtGis Apr 10 '21 at 16:03
  • Yes. You can use the par("usr") function to get the plot limits of the current plot. That would give you the information you need to scale the arrows to fit within the limits – Tyler Apr 15 '21 at 14:37
  • I cant figure it out why if I use ``choices = c(x,y)`` (so that the user can enter the LD to be plotted) the function does not work: Error in choices[x] : invalid subscript type 'list'. Needless to say, other parts would be modified accordingly, like for example ``x1 = myscale * heads[,choices[x]]``. Cant exactly locate what's causing the error. Any clue? – NewAtGis May 02 '21 at 07:01
  • @newatgis what is the value of 'x'? The error suggests it's a list, not an integer. It's hard to debug fragments of code in a comment, maybe ask a new question if you need more help – Tyler May 02 '21 at 15:33
  • x and y are as simple as x=1, y=2, so they are not a list. That's why I cant really understand where the issue lies. – NewAtGis May 03 '21 at 11:01
  • @Tyler I think I fixed the issue. I would like to integrate your code into a function of mine (which will end up in an R package) and I would like to give you credit for that. How can I go about that? – NewAtGis May 04 '21 at 12:02
  • you can get my contact info here: https://plantarum.ca/about/ – Tyler May 04 '21 at 14:57
3

My understanding is that biplots of linear discriminant analyses can be done, it is implemented in fact also in R package ggbiplot, see https://github.com/vqv/ggbiplot/tree/experimental and package ggord, see https://github.com/fawda123/ggord, for your example:

install.packages("devtools")
library(devtools)
install_github("fawda123/ggord")
library(ggord)
ord <- lda(Species ~ ., iris, prior = rep(1, 3)/3)
ggord(ord, iris$Species)

enter image description here

Also the book "Biplots in practice" by M. Greenacre has one chapter (chapter 11) on it and in Figure 11.5 it shows a biplot of a linear discriminant analysis of the iris dataset: enter image description here

Tom Wenseleers
  • 7,535
  • 7
  • 63
  • 103
0

You can achieve this using the ggord package from github. The dataset used is IRIS dataset

# --- data partition -- #
set.seed(555)
IRSam <- sample.int(n = nrow(IR), size = floor(.60*nrow(IR)), replace = FALSE, prob = NULL)
IRTrain <- IR[IRSam,]
IRTest <- IR[-IRSam,]    

# --- Prediction --- #
p<- predict(IR.lda, IRTrain)

# --- plotting a biplot --- #
library(devtools)
# install_github('fawda123/ggord') --- Used to install ggord from github we need to run devtools to achieve this.
library(ggord)
ggord(IR.lda, IRTrain$Species, ylim=c(-5,5), xlim=c(-10,10))
Keerthesh Kumar
  • 201
  • 2
  • 8