Search code examples
rfor-loopshapefile

Using st_write in a for loop to export multiple shape files


I am trying to create multiple shapefiles (and dataframes) based on unique field values within FIREYEAR. I have been able to produce individual dataframes based on each year with the corrrect number of observations in each one. When using st_write to create shapefiles though they come out incorrectly. My code creates individual shapefiles with the correct name but each shapefile contains all values from every year. In this case each exported shapefile should have 2 observations but comes out with 4. 2 from 1985 and 2 from 1986. How can I implement st_write in my for loop to correctly export multiple shape files? Thanks.

Sample data

df1 <- data.frame(FIRENAME = c("Gold", "Tree", "Tank", "Green_1"),
                  UNIQFIREID = c("1985-AZASF-000285", "1985-AZASF-000286", "1985-AZASF-000287", "1985-AZASF-000288"),
                  FIREYEAR = c("1985", "1985", "1986", "1986"),
                  TOTALACRES = c(60, 70, 80, 90))

# I left out the geometry which was sfc_MULTIPOLYGONs and didn't seem to make a difference for the example.

For loop and st_write code

for(i in unique(df1$FIREYEAR)) {
  list_data <- split(df1, df1$FIREYEAR)
  names(list_data) <- paste0("df_", names(list_data))
  list2env(list_data, .GlobalEnv)
  st_write(df1, dsn = "F:/School/NAU/Forestry/Masters/MSF_Project_2-7-2020/Michaels_Analysis/Fire_History/R", paste0(i), driver = "ESRI Shapefile", append = TRUE)
}

Solution

  • The problem with this code:

    for(i in unique(df1$FIREYEAR)) {
      list_data <- split(df1, df1$FIREYEAR)
      names(list_data) <- paste0("df_", names(list_data))
      list2env(list_data, .GlobalEnv)
      st_write(df1, dsn = "F:/School/NAU/Forestry/Masters/MSF_Project_2-7-2020/Michaels_Analysis/Fire_History/R", paste0(i), driver = "ESRI Shapefile", append = TRUE)
    }
    

    is that no matter what you are doing inside this loop, the line:

    st_write(df1, dsn = "....
    

    is only going to write df1 again and again.

    Either loop over the unique values and subset the dataframe, writing only the subset, something like this (untested because currently doing an upgrade... but I think it works):

    ## loop over all unique fire years:
    for(year in unique(df1$FIREYEAR)) {
    ## subset only that year's data. 
      df.year = df1[df1$FIREYEAR==year,]
    ## construct a file name like df_1986.shp and save this data:
      file.name = paste0("df_",year,".shp")
      st_write(df.year, file.name)
    }
    

    or use split and loop over the elements of the list that is returned.

    You don't need extraneous packages to do simple things like this.