Home > Software design >  Losing sf class from for loop
Losing sf class from for loop

Time:07-08

I am trying to find the area of each polygon in my sf data.frame that does not intersect all of the other polygons. I've developed a for loop to determine the non-intersected polygons and save them into a new data.frame but that causes it to lose the sf class. Is there a way to perform this in a way that the class is not lost and I can plot the results?

Some data:

library(sf)
set.seed(1234)
xcoord <- runif(10, min=0,max=10) 
ycoord <- runif(10,min=0,max=10)
points <- data.frame(x=xcoord,y=ycoord)
pointssf <- st_as_sf(points,coords=c('x','y'),dim='XY')
#create buffers from points
buffer <- st_buffer(pointssf,2)

#My attempt
buffsarea <- st_area(buffer)
#initialize data.frame
intbuffs <- data.frame(matrix(ncol = ncol(buffer), nrow = nrow(buffer)))
for(i in 1:nrow(buffer)){
  rem1 = buffer[i,1]
  left1 = buffer[-i,1]
  leftunion = st_union(left1)
  ab = st_covered_by(rem1,leftunion,sparse=F)
  if(ab[[1]]==F){
    intbuffs[i,1]= st_difference(rem1,leftunion)
  }
  else{
  intbuffs[i,1] = 0 #for cases where entire buffer intersects
  }
}
t_area(intbuffs)

Error in UseMethod("st_area") : no applicable method for 'st_area' applied to an object of class "data.frame"

CodePudding user response:

data.frame objects cannot contain sf objects, so if you want to save sf objects using a loop, you should instead use list objects. In addition, you can use lapply to calculate the area of the resulting sf objects, and for objects without features set its area = 0 .

# Make list instead of data.frame so sf objects can be saved in each entry
intbuffs <- vector("list", nrow(buffer))

for(i in 1:nrow(buffer)){
  rem1 = buffer[i,1]
  left1 = buffer[-i,1]
  leftunion = st_union(left1)
  ab = st_covered_by(rem1,leftunion,sparse=F)
  intbuffs[[i]]= st_difference(rem1,leftunion)
}

# plot results
plot(intbuffs[[2]])

# Calculate area
resul <- lapply(intbuffs, function(x){
  # Check for sf with 0 features
  ifelse(nrow(x) == 0, 0, st_area(x))
  })

# Convert from list to vector
unlist(resul)
  • Related