title: calculate distance between each pair of coordinates in wide dataframe
body: <p>I want to calculate the distance between two linked set of spatial coordinates (<code>program</code> and <code>admin</code> in my fake dataset). The data are in a wide format, so both pairs of coordinates are in the same row.</p>
  
  <pre><code>library(sp)
  set.seed(1)
  n &lt;- 100
  program.id &lt;- seq(1, n)
  c1 &lt;- cbind(runif(n, -90, 90), runif(n, -180, 180))
  c2 &lt;- cbind(runif(n, -90, 90), runif(n, -180, 180))
  dat &lt;- data.frame(cbind(program.id, c1, c2))
  names(dat) &lt;- c("program.id", "program.lat", "program.long", "admin.lat", "admin.long")
  head(dat)
  #       program.id program.lat program.long  admin.lat  admin.long
  # 1              1   -42.20844     55.70061 -41.848523   62.536404
  # 2              2   -23.01770    -52.84898 -50.643849 -145.851172
  # 3              3    13.11361    -82.70635   3.023431   -2.665397
  # 4              4    73.47740    177.36626 -41.588893  -13.841337
  # 5              5   -53.69725     48.05758 -57.389701  -44.922049
  # 6              6    71.71014   -103.24507   3.343705  176.795719
  </code></pre>
  
  <p>I know how to create a matrix of distances among <code>program</code> or <code>admin</code> using the <code>sp</code> package:</p>
  
  <pre><code>ll &lt;- c("program.lat", "program.long")
  coords &lt;- dat[ll]
  dist &lt;- apply(coords, 1, 
                function(eachPoint) spDistsN1(as.matrix(coords),
                                              eachPoint, longlat=TRUE))
  </code></pre>
  
  <p>But what I want to do is create a nx1 vector of distances (<code>dist.km</code>) between each pair of coordinates and add it to <code>dat</code>. </p>
  
  <pre><code>#       program.id program.lat program.long  admin.lat  admin.long  dist.km
  # 1              1   -42.20844     55.70061 -41.848523   62.536404   567.35
  # 2              2   -23.01770    -52.84898 -50.643849 -145.851172  8267.86
  # ...
  </code></pre>
  
  <p>Any suggestions? I've spent a while going through old SO questions, but nothing seems quite right. Happy to be proven wrong.</p>
  
  <p><strong>Update</strong></p>
  
  <p>@Amit's solution works for my toy dataset:</p>
  
  <pre><code>apply(dat,1,function(x) spDistsN1(matrix(x[2:3],nrow=1),x[3:4],longlat=TRUE))
  </code></pre>
  
  <p>But I think I need to swap the order of the lat, long the order of the lat long columns so long comes before lat. From <code>?spDistsN1</code>:</p>
  
  <pre><code>pts: A matrix of 2D points, first column x/longitude, second column y/latitude, or a SpatialPoints or SpatialPointsDataFrame object
  </code></pre>
  
  <p>Also, unless I've misunderstood the logic, I think Amit's solution should grab cols [2:3] and [4:5], not [2:3] and [3:4]. </p>
  
  <p>My challenge now is applying this to my actual data. I've reproduced a portion below.</p>
  
  <pre><code>library(sp)
  dat &lt;- structure(list(ID = 1:4, 
                        subcounty = c("a", "b", "c", "d"), 
                        pro.long = c(33.47627919, 31.73605491, 31.54073482, 31.51748984), 
                        pro.lat = c(2.73996953, 3.26530095, 3.21327597, 3.17784981), 
                        sub.long = c(33.47552, 31.78307, 31.53083, 31.53083), 
                        sub.lat = c(2.740362, 3.391209, 3.208736, 3.208736)), 
                   .Names = c("ID", "subcounty", "pro.long", "pro.lat", "sub.long", "sub.lat"),     
                   row.names = c(NA, 4L), class = "data.frame")
  head(dat) 
  #     ID subcounty pro.long  pro.lat sub.long  sub.lat
  #  1   1         a 33.47628 2.739970 33.47552 2.740362
  #  2   2         b 31.73605 3.265301 31.78307 3.391209
  #  3   3         c 31.54073 3.213276 31.53083 3.208736
  #  4   4         d 31.51749 3.177850 31.53083 3.208736
  apply(dat, 1, function(x) spDistsN1(matrix(x[3:4], nrow=1),
                                      x[5:6],
                                      longlat=TRUE)) 
  </code></pre>
  
  <p>I get the error: <code>Error in spDistsN1(matrix(x[3:4], nrow = 1), x[5:6], longlat = TRUE) : pts must be numeric</code></p>
  
  <p>I'm confused because these columns are numeric: </p>
  
  <pre><code>&gt; is.numeric(dat$pro.long)
  [1] TRUE
  &gt; is.numeric(dat$pro.lat)
  [1] TRUE
  &gt; is.numeric(dat$sub.long)
  [1] TRUE
  &gt; is.numeric(dat$sub.lat)
  [1] TRUE
  </code></pre>