3
$\begingroup$

I have two data frames, the first indicating customer locations and the second indicating facility locations. I want to calculate the average distance of all customers to the closest facility location

Facility locations are calculated as follows:

grid_size <- 20
m <- 10
facility_locations <- data.frame(
  ID = 1:m,
  x = runif(m) * grid_size,
  y = runif(m) * grid_size)

And around that, customers are located in the following fashion:

generateGaussianData <- function(n, center, sigma, label) {
  data = rmvnorm(n, mean = center, sigma = sigma)
  data = data.frame(data)
  names(data) = c("x", "y")
  data = data %>% mutate(class=factor(label))
  data
}
dataset1 <- {
  # cluster 1
  q = 30
  center = c(facility_locations[1,2], facility_locations[1,3])
  sigma = matrix(c(3, 0, 0, 3), nrow = 2)
  data1 = generateGaussianData(q, center, sigma, 1) 

#cluster 2 - 10 constructued in the same way#

data = bind_rows(data1, data2, data3, data4, data5, data6, data7, data8, data9,
                   data10)
}

This is based on : https://www.r-bloggers.com/2018/11/generate-datasets-to-understand-some-clustering-algorithms-behavior/

Preferably, I would get a formula that gives me the average distance of all customers to the closest facility location. Note this is can be different from the center of the cluster in which they are generated due to the spread.

$\endgroup$
2
  • 2
    $\begingroup$ Wouldn't that be better to ask this question at stackoverflow.com? I am not sure if this question is relevant to OR. $\endgroup$
    – whitepanda
    Commented Jul 13, 2022 at 13:31
  • 1
    $\begingroup$ Location problems seem very relevant to OR.SE . $\endgroup$ Commented Jul 14, 2022 at 13:06

2 Answers 2

2
$\begingroup$

It is not explicit in your question, so I am going to assume that you want to match each customer to the closest facility regardless of label (meaning a customer with label 3 might be matched with facility 7). The following function takes as input the x and y coordinates of a customer and returns the minimum euclidean distance to any facility.

closest <- function(x, y) {
  apply(facility_locations, 1,
        function(x) norm(as.numeric(x[2:3]) - c(x, y), type = "2")) %>% 
     min()
}

The next bit of code creates a new column (MinDist) in the data dataframe, listing the minimum distance to any facility for each customer.

data <- data %>% rowwise() %>% mutate(MinDist = closest(x, y))

From there, you can compute mean, median or any other static you like from the new column.

$\endgroup$
2
  • $\begingroup$ Im not sure why, but as of today, it keeps giving me wrong values. I have tried cleaning the full environment and rerunning everything. What could be the issue? I have not changed anything to the code above nor have I entered other code between the code above and the answer provided. I know the values are wrong as I also calculate some random distances with a normal distance function $\endgroup$
    – user9867
    Commented Jul 22, 2022 at 9:20
  • $\begingroup$ Did you add any libraries that overwrote the norm() function? A quick test would be to change norm(...) to base::norm(...) in the definition of closest. Other than that (which granted is a long shot), I think you would have to post a minimal example that shows the problem. (Here "minimal" means only the code necessary to produce and confirm an incorrect value.) $\endgroup$
    – prubin
    Commented Jul 22, 2022 at 15:06
2
$\begingroup$

Use dist (for Cartesian coordinates) or geosphere::distm (for latitude and longitude) to create a distance matrix. Use apply to find the minimum distance to a facility, for each customer. Find mean from there.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.