4

I have an sf point dataframe, with a single incorrect point. I know what it's coordinates should be, but I'm not sure how best to directly edit them. I'm aiming for a conditional edit like the following

new_point <- st_point(c(145.38626, -16.43350)) %>% 
               st_sfc(crs = 4283) %>% 
               st_transform(., 3577)

allpoints_clean <- allpoints %>%
  mutate(geometry = ifelse(s_id == '1', st_geometry(new_point), geometry)

but this produces the error 'no simple features geometry column present', which is definitely not the case. What should I be doing instead?

6
  • I think direct overwrite with assignment is best in this case. Explore allpoints$geometry[[1]] with str and unclass to get the idea. Sf was not designed with this kind of flexibility in mind, but it's light enough to diy in cases like this.
    – mdsumner
    Commented Jun 21, 2017 at 6:39
  • And just quietly, this is exactly why spbabel exists. I am happy to help find a solution but it might be best in another forum (like the spbabel issues on github)
    – mdsumner
    Commented Jun 21, 2017 at 6:46
  • huh. yeah ok allpoints$geometry[allpoints$sid %in% 'id1'] <- new_point works as an overwrite, but allpoints[allpoints$sid %in% 'id1', allpoints$geometry] <- new_point doesn't (because list-column??)
    – obrl_soil
    Commented Jun 21, 2017 at 6:53
  • 1
    Run ifelse(p$s_id == 1, st_geometry(new_point), p$geometry) and you'll see the spatialness is dropped by ifelse. See my additional edit for tidyverse solution.
    – Spacedman
    Commented Jun 21, 2017 at 6:59
  • excellent, thanks - spatialness is dropped because the test in ifelse refers to a non-spatial object?
    – obrl_soil
    Commented Jun 21, 2017 at 7:05

1 Answer 1

6

Create a reproducible example:

> p = st_sf(a=3, geometry = st_sfc(st_point(1:2)))
> p = rbind(p,p,p,p,p)
> p$s_id = c(0,0,1,0,0)
> p
Simple feature collection with 5 features and 2 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 1 ymin: 2 xmax: 1 ymax: 2
epsg (SRID):    NA
proj4string:    NA
  a   geometry s_id
1 3 POINT(1 2)    0
2 3 POINT(1 2)    0
3 3 POINT(1 2)    1
4 3 POINT(1 2)    0
5 3 POINT(1 2)    0

Then its just a conditional replacement into the geometry column:

> p$geometry[p$s_id==0]=new_point
> p
Simple feature collection with 5 features and 2 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 1 ymin: 2 xmax: 1 ymax: 2
epsg (SRID):    NA
proj4string:    NA
  a                       geometry s_id
1 3 POINT(1433173.30406075 -182...    0
2 3 POINT(1433173.30406075 -182...    0
3 3                     POINT(1 2)    1
4 3 POINT(1433173.30406075 -182...    0
5 3 POINT(1433173.30406075 -182...    0

Oops I've replaced s_id==0 lines (demonstrating how you can replace multiple geometries). Replace with s_id==1 for your use!

The problem in your example is the ifelse is returning a plain list. Wrap it in st_sfc and your mutate works..

> p = rbind(p,p,p,p,p)
> p$s_id=c(0,0,1,0,0)
> p
Simple feature collection with 5 features and 2 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 1 ymin: 2 xmax: 1 ymax: 2
epsg (SRID):    NA
proj4string:    NA
  a   geometry s_id
1 3 POINT(1 2)    0
2 3 POINT(1 2)    0
3 3 POINT(1 2)    1
4 3 POINT(1 2)    0
5 3 POINT(1 2)    0
> pm = p %>% mutate(geometry = st_sfc(ifelse(s_id == 1, st_geometry(new_point), geometry)))
> pm
Simple feature collection with 5 features and 2 fields
geometry type:  POINT
dimension:      XY
bbox:           xmin: 1 ymin: -1824335 xmax: 1433173 ymax: 2
epsg (SRID):    NA
proj4string:    NA
  a s_id                       geometry
1 3    0                     POINT(1 2)
2 3    0                     POINT(1 2)
3 3    1 POINT(1433173.30406075 -182...
4 3    0                     POINT(1 2)
5 3    0                     POINT(1 2)
1
  • yep that's it, see comment above - although there seems to be some issues around index-referencing df's with list-columns that I don't fully understand yet.
    – obrl_soil
    Commented Jun 21, 2017 at 6:55

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.