0

I have a data frame in R which is of size nx4. I am attempting to loop through it and perform a computation to add to the "distances" vector. x0 is a vector of length 3. I attempt to run the following code

trainData = data.frame(x1,x2,x3,y)

for (j in 1:n) {
    distances[j] = sqrt(sum((x0 - trainData[j,1:3])^2))
}

I get the following error:

Error in Ops.data.frame(x0, trainData[j, 1:3]) : 
  ‘-’ only defined for equally-sized data frames

However, the 2 values being subtracted are the same length, and I can run it without looping, ie

sqrt(sum((x0 - trainData[1,1:3])^2))

I'm unable to find the reason for this, any help is appreciated.

doug
  • 103
  • 1
  • Please share sample of your data using `dput()` (not `str` or `head` or picture/screenshot) so others can help. See more here https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example?rq=1 – Tung Sep 20 '18 at 02:14
  • Perhaps `n <- nrow(trainData)` before the loop? Close vote because we cannot tell what your x0 value might be. – IRTFM Sep 20 '18 at 04:01

2 Answers2

0

You want to use the dist() function to calculate your distance. Also, avoid using loops and look at the apply family of functions.

library(dplyr)

set.seed(1724)
trainData <- data.frame(x1 = runif(4, 1, 10), x2 = runif(4, 1, 10), x3 = runif(4, 1, 10), y = runif(4, 1, 10))

mutate(trainData,
       dist = apply(trainData,
                    1,
                    function(x, y = runif(3, 1, 10)) {
                      dist(rbind(x[1:3], y), method = "euclidean")
                    }))

#         x1       x2       x3        y      dist
# 1 5.890667 7.156956 6.946917 6.580706  6.188533
# 2 3.060810 1.117295 7.676836 7.965404  5.193822
# 3 8.058110 5.518819 2.687567 3.832825 10.520283
# 4 8.405847 1.326119 3.533277 6.804517  8.390918
Paul
  • 2,877
  • 1
  • 12
  • 28
0

I'm not sure what the original issue was, but I've got things working by taking Paul's advice and replacing the loop with:

  distances = apply(trainData, 1, function(x) dist(rbind(x0,x)))
doug
  • 103
  • 1