Find the length of a road in R

Advertisements

Question

I have a dataframe df which contains cartesian coordinates of a hypothetical road. I want to find the length of the road. Following is a plot:

library(ggplot2)
ggplot(df) +
  geom_point(aes(x, y2))

My attempt to find the length:

I tried converting df to an sf object and then find length, but it didn’t work as expected:

library(sf)
df_sf <- st_as_sf(df, coords = c("x", "y2"))

> sf::st_length(df_sf)
  [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 [36] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 [71] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[106] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Is there a way I can convert the df to a polyline sf object and then find the length? Any other suggestions?

Data

df <- structure(list(x = c(12158, 12158, 12158, 12158, 12158, 12158, 
12158, 12158, 12158, 12158, 12157.999023, 12158, 12158, 12156.886719, 
12154.849609, 12151.196289, 12147.6875, 12143.267578, 12137.9375, 
12131.700195, 12124.556641, 12116.507813, 12107.557617, 12097.708984, 
12086.962891, 12075.326172, 12062.798828, 12049.386719, 12035.092773, 
12019.921875, 12003.879883, 11986.969727, 11969.197266, 11950.568359, 
11931.087891, 11910.761719, 11889.597656, 11867.599609, 11844.777344, 
11821.134766, 11796.681641, 11771.423828, 11745.369141, 11718.525391, 
11690.901367, 11662.505859, 11633.345703, 11603.432617, 11572.773438, 
11541.37793, 11509.255859, 11476.417969, 11442.87207, 11408.630859, 
11373.703125, 11338.099609, 11301.831055, 11264.910156, 11227.345703, 
11189.151367, 11150.337891, 11110.916016, 11070.899414, 11030.299805, 
10989.128906, 10947.400391, 10905.125, 10862.318359, 10818.991211, 
10794.041016, 10746.004883, 10685.342773, 10493.634766, 10488.304688, 
9822.144531, 9590.665039, 9495.904297, 9393.224609, 9333.71875, 
9274.916016, 9216.833008, 9159.488281, 9102.900391, 9047.083984, 
8992.058594, 8937.839844, 8884.444336, 8831.888672, 8780.1875, 
8729.358398, 8679.416016, 8630.375, 8582.251953, 8535.05957, 
8488.813477, 8443.52832, 8399.21582, 8355.890625, 8313.566406, 
8272.255859, 8231.970703, 8192.724609, 8154.52832, 8117.394043, 
8081.33252, 8046.355469, 8012.473633, 7979.696289, 7948.03418, 
7917.49707, 7888.09375, 7859.833984, 7832.725586, 7806.776855, 
7781.996094, 7758.390625, 7735.967773, 7714.734375, 7694.696777, 
7675.861328, 7658.23291, 7641.818359, 7626.621094, 7612.646973, 
7599.899414, 7588.383301, 7578.101074, 7569.056152, 7561.251953, 
7554.689941, 7548.160156, 7544.127441, 7540.84082, 7538, 7538, 
7538), y2 = c(15255, 14520, 13200, 11880, 10560, 9240, 7920, 
6600, 5280, 3960, 2786.666992, 2640, 1916.935059, 1725.494141, 
1646.221191, 1567.054199, 1514.8125, 1462.640137, 1410.552734, 
1358.566406, 1306.697266, 1254.959961, 1203.371582, 1151.947266, 
1100.702148, 1049.652832, 998.813965, 948.202148, 897.831543, 
847.718262, 797.877441, 748.32373, 699.073242, 650.140137, 601.539551, 
553.286621, 505.395508, 457.881348, 410.758301, 364.040527, 317.742676, 
271.878418, 226.462402, 181.507324, 137.02832, 93.037598, 49.549316, 
6.57666, -35.867188, -77.769531, -119.118164, -159.899414, -200.101074, 
-239.711914, -278.71875, -317.109863, -354.874023, -391.999023, 
-428.474609, -464.288574, -499.430664, -533.890137, -567.65625, 
-600.719238, -633.067871, -664.693848, -695.585938, -725.736328, 
-755.134277, -771.569336, -802.256348, -839.523926, -951.065918, 
-954.111816, -1334.774658, -1468.841064, -1526.266846, -1591.573242, 
-1631.31665, -1672.092529, -1713.888184, -1756.691406, -1800.489014, 
-1845.267334, -1891.012939, -1937.712158, -1985.350342, -2033.913086, 
-2083.385742, -2133.753174, -2185, -2237.110596, -2290.069336, 
-2343.859619, -2398.465576, -2453.870117, -2510.056641, -2567.007813, 
-2624.706787, -2683.135254, -2742.276123, -2802.11084, -2862.621338, 
-2923.789307, -2985.596191, -3048.022949, -3111.050537, -3174.659912, 
-3238.831543, -3303.546143, -3368.783691, -3434.524414, -3500.748535, 
-3567.435547, -3634.56543, -3702.117188, -3770.071045, -3838.405762, 
-3907.100586, -3976.134766, -4045.486816, -4115.13623, -4185.061523, 
-4255.241211, -4325.654297, -4396.279297, -4467.094238, -4538.078125, 
-4609.208496, -4680.464844, -4770.95166, -4848.422363, -4943.858398, 
-5270.765625, -5280, -7920)), row.names = c(NA, -136L), class = "data.frame")

>Solution :

To do this in sf, you can convert into a linestring and use st_length

sf::st_length(sf::st_linestring(as.matrix(df)))
#> [1] 25077.29

Note though that you don’t need sf at all here, as you get the same result using a basic Euclidean distance calculation:

sum(sqrt(diff(df$x)^2 + diff(df$y2)^2))
#> [1] 25077.29

Leave a ReplyCancel reply