library(tidyverse)
library(MASS)
library(magrittr)
set.seed(41)

1 Generate data

theta <- rnorm(1) # angle
A <- matrix(rnorm(100 * 2), 100, 2) # rotation vector
A <- A %*% diag(c(3, 1)) %*% matrix(c(cos(theta), sin(theta), -sin(theta), cos(theta)), 2, 2)
Sigma <- var(A)
Sigma
         [,1]     [,2]
[1,] 5.238469 4.280309
[2,] 4.280309 5.060916

Bias vectors

ma <- c(2, 0)
mb <- c(5, 2)

Generate two multivariate gaussians

a <- mvrnorm(n = 1000, ma, Sigma)
b <- mvrnorm(n = 1000, mb, Sigma)

Print covariance matrices

a %>% as.data.frame %>% cov
         V1       V2
V1 5.193249 4.379969
V2 4.379969 5.332480
b %>% as.data.frame %>% cov
         V1       V2
V1 5.195009 4.128270
V2 4.128270 4.779776

2 LDA

Compute difference vector and LDA vector

mdiff <- mb - ma
mdiff_lda <- solve(Sigma, mdiff)

3 Display

Create data frame for the vectors

mdiff_df <- data_frame(x2 = mdiff[1], y2 = mdiff[2], x1 = 0, y1 = 0)
mdiff_lda_df <- data_frame(x2 = mdiff_lda[1], y2 = mdiff_lda[2], x1 = 0, y1 = 0)
df <- 
  bind_rows(
    as.data.frame(a) %>% mutate(class = "a"),
    as.data.frame(b) %>% mutate(class = "b")
    )

Plot data

ggplot() + 
  geom_point(data = df, aes(V1, V2, color = class), alpha = .5) + 
  coord_equal()

Plot data with difference vector (black) and LDA vector (blue)

ggplot() + 
  geom_point(data = df, aes(V1, V2, color = class), alpha = .5) + 
  geom_segment(data = mdiff_df, aes(x = x1, y = y1, xend = x2, yend = y2), arrow = arrow()) +
  geom_segment(data = mdiff_lda_df, aes(x = x1, y = y1, xend = x2, yend = y2), arrow = arrow(), color = "blue") +
  coord_equal() + 
  facet_wrap(~class) +
  ggtitle("Difference vector (black) and LDA vector (blue)")

NA
NA
LS0tCnRpdGxlOiAiTERBIHZzIGRpZmZlcmVuY2UgdmVjdG9yIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRoZW1lOiBsdW1lbgotLS0KCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkobWFncml0dHIpCmBgYAoKCmBgYHtyfQpzZXQuc2VlZCg0MSkKYGBgCgojIEdlbmVyYXRlIGRhdGEKCmBgYHtyfQp0aGV0YSA8LSBybm9ybSgxKSAjIGFuZ2xlCkEgPC0gbWF0cml4KHJub3JtKDEwMCAqIDIpLCAxMDAsIDIpICMgcm90YXRpb24gdmVjdG9yCkEgPC0gQSAlKiUgZGlhZyhjKDMsIDEpKSAlKiUgbWF0cml4KGMoY29zKHRoZXRhKSwgc2luKHRoZXRhKSwgLXNpbih0aGV0YSksIGNvcyh0aGV0YSkpLCAyLCAyKQpTaWdtYSA8LSB2YXIoQSkKU2lnbWEKYGBgCgpCaWFzIHZlY3RvcnMKCmBgYHtyfQptYSA8LSBjKDIsIDApCm1iIDwtIGMoNSwgMikKYGBgCgpHZW5lcmF0ZSB0d28gbXVsdGl2YXJpYXRlIGdhdXNzaWFucwoKYGBge3J9CmEgPC0gbXZybm9ybShuID0gMTAwMCwgbWEsIFNpZ21hKQpiIDwtIG12cm5vcm0obiA9IDEwMDAsIG1iLCBTaWdtYSkKYGBgCgoKUHJpbnQgY292YXJpYW5jZSBtYXRyaWNlcwoKYGBge3J9CmEgJT4lIGFzLmRhdGEuZnJhbWUgJT4lIGNvdgoKYiAlPiUgYXMuZGF0YS5mcmFtZSAlPiUgY292CmBgYAoKIyBMREEgCgpDb21wdXRlIGRpZmZlcmVuY2UgdmVjdG9yIGFuZCBMREEgdmVjdG9yCgpgYGB7cn0KbWRpZmYgPC0gbWIgLSBtYQptZGlmZl9sZGEgPC0gc29sdmUoU2lnbWEsIG1kaWZmKQpgYGAKCiMgRGlzcGxheSAKCkNyZWF0ZSBkYXRhIGZyYW1lIGZvciB0aGUgdmVjdG9ycwoKYGBge3J9Cm1kaWZmX2RmIDwtIGRhdGFfZnJhbWUoeDIgPSBtZGlmZlsxXSwgeTIgPSBtZGlmZlsyXSwgeDEgPSAwLCB5MSA9IDApCm1kaWZmX2xkYV9kZiA8LSBkYXRhX2ZyYW1lKHgyID0gbWRpZmZfbGRhWzFdLCB5MiA9IG1kaWZmX2xkYVsyXSwgeDEgPSAwLCB5MSA9IDApCmBgYAoKCmBgYHtyfQpkZiA8LSAKICBiaW5kX3Jvd3MoCiAgICBhcy5kYXRhLmZyYW1lKGEpICU+JSBtdXRhdGUoY2xhc3MgPSAiYSIpLAogICAgYXMuZGF0YS5mcmFtZShiKSAlPiUgbXV0YXRlKGNsYXNzID0gImIiKQogICAgKQpgYGAKClBsb3QgZGF0YQoKYGBge3J9CmdncGxvdCgpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZGYsIGFlcyhWMSwgVjIsIGNvbG9yID0gY2xhc3MpLCBhbHBoYSA9IC41KSArIAogIGNvb3JkX2VxdWFsKCkKYGBgCgpQbG90IGRhdGEgd2l0aCBkaWZmZXJlbmNlIHZlY3RvciAoYmxhY2spIGFuZCBMREEgdmVjdG9yIChibHVlKQoKYGBge3J9CmdncGxvdCgpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZGYsIGFlcyhWMSwgVjIsIGNvbG9yID0gY2xhc3MpLCBhbHBoYSA9IC41KSArIAogIGdlb21fc2VnbWVudChkYXRhID0gbWRpZmZfZGYsIGFlcyh4ID0geDEsIHkgPSB5MSwgeGVuZCA9IHgyLCB5ZW5kID0geTIpLCBhcnJvdyA9IGFycm93KCkpICsKICBnZW9tX3NlZ21lbnQoZGF0YSA9IG1kaWZmX2xkYV9kZiwgYWVzKHggPSB4MSwgeSA9IHkxLCB4ZW5kID0geDIsIHllbmQgPSB5MiksIGFycm93ID0gYXJyb3coKSwgY29sb3IgPSAiYmx1ZSIpICsKICBjb29yZF9lcXVhbCgpICsgCiAgZmFjZXRfd3JhcCh+Y2xhc3MpICsKICBnZ3RpdGxlKCJEaWZmZXJlbmNlIHZlY3RvciAoYmxhY2spIGFuZCBMREEgdmVjdG9yIChibHVlKSIpCgoKYGBgCgo=