'min values by row and column of a distance matrix "without replacement"

I have a distance matrix. I would essentially like to perform the equivalent of matching without replacement on the minimum value by row and column.

Here is some reproducible code.

  x1 <- c(runif(100, 0,5),runif(100, 1,6))
  x2 <- c(runif(100, 0,5),runif(100, 1,6))
  t <- c(rep("C",100),rep("T",100))
  t.num <- ifelse(t=="C",0,1)
  y <- 2*ifelse(t=="C",0,1) + x1 + x2 + rnorm(200)
    
  x <- list(x1=x1,x2=x2,t=t, t.num=t.num, y=y) %>% as.data.frame()

  X <- x[,1:2]
  
  #calculate the mahalanobis distance between rows
  cx <- cov(X)
  out <- lapply(1:nrow(X), function(i) {
    mahalanobis(x = X, 
                center = do.call("c", X[i, ]),
                cov = cx)
  })

  #matrix of mahalanobis distances
  d.m <- as.dist(do.call("rbind", out), upper = T) %>% as.matrix() %>% as.data.frame()

  #remove irrelevant values from matrix 
  #(those where it matches with itself or control to control or treat to treat)
  # d.m[d.m==0] <- NA
  d.m[x$t=="C", x$t=="C"] <- NA
  d.m[x$t=="T", x$t=="T"] <- NA

d.m is the distance matrix. Currently I am using a for loop with the which function to locate the minimum value in the matrix, store the position then remove the data from that row and column before moving on to finding the next minimum position.

The problem I have is that computationally, this process is way more expensive than I would like further down the line (I loop through 180x100 iterations on randomly generated date).

I have attempted to investigate an elegant solution via the usual means to no avail so I am appealing to the wider community (for the first time!). I have already been helped tremendously by this online resource so I have my fingers crossed. TIA!!!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source