3

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 Jun 21 '17 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 Jun 21 '17 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 Jun 21 '17 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 Jun 21 '17 at 6:59
  • excellent, thanks - spatialness is dropped because the test in ifelse refers to a non-spatial object? – obrl_soil Jun 21 '17 at 7:05
4

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 Jun 21 '17 at 6:55

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.