I am trying to sort my data based on the latitude and longitude. I have an sf object in R, which essentially stores the latitude and longitude as a separate column called geometry.

See below:

> head(barfly.pr.sp)
Simple feature collection with 6 features and 14 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 76.99832 ymin: 10.04038 xmax: 77.0799 ymax: 10.1619
epsg (SRID):    4326
proj4string:    +proj=longlat +datum=WGS84 +no_defs

    effort_distance_km effort_area_ha reviewed                  geometry
0                 0.00              0    FALSE  POINT (77.0351 10.14666)
0.1              24.14              0    FALSE   POINT (77.066 10.08324)
0.2               8.00              0    FALSE POINT (77.05931 10.09309)
0.3               3.00              0    FALSE  POINT (77.0799 10.04038)
0.4               1.20              0    FALSE  POINT (76.99832 10.1619)
0.5               2.50              0    FALSE POINT (77.06757 10.15112)

I am trying to sort the same based on geometry and I get this error:

> barfly.pr.sp <-  barfly.pr.sp[order(barfly.pr.sp$geometry),]
Error in Ops.sfc(xi, xj) : operation > not supported

I also tried dplyr::group_by() and I got the following error:

barfly.pr.sp <-  barfly.pr.sp %>% group_by(geometry)
Error in grouped_df_impl(data, unname(vars), drop) : 
  Column `geometry` can't be used as a grouping variable because it's a sfc_POINT/sfc

Any suggestions?


Never mutate your data with temporary values. Create new objects with temporary values. Here's a solution that does not mutate the original data in any way apart from the ordering, and also only uses base R operations:

nc <- st_read(system.file(package = "sf", "shape/nc.shp"))
xy = st_coordinates(st_centroid(nc))

Now sort by X coord first and use Y to break ties (which are probably unlikely for polygon centroids, but might happen with discrete point data).

nc.sort = nc[order(xy[,"X"], xy[,"Y"]),]

As a test, check that the difference in successive X coordinates is now non-negative:

> range(diff(st_coordinates(st_centroid(nc.sort))[,1]))
[1] 0.001191683 0.282903325

Compare with original which was not in increasing X coordinates:

> range(diff(st_coordinates(st_centroid(nc))[,1]))
[1] -7.290978  7.171192
| improve this answer | |

I was just about to answer when jsta posted. I will post an alternative solution anyways that is a bit less code, sorts on x and y and removes x and y when finished:


nc <- st_read(system.file(package = "sf", "shape/nc.shp"))
nc <- st_centroid(nc)

nc.sort <- nc %>% cbind(st_coordinates(.)) %>%
  arrange(X, Y) %>%
  select(-X, -Y)
| improve this answer | |
  • 1
    Why would you risk mutating the object twice (first adding the columns and then removing them) if you can use simple indices and not mess with your data? – Joris Meys Nov 15 '18 at 10:29
  • good point. Spacedman's answer is better – sebdalgarno Nov 15 '18 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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