R, sf, st_write, ESRI Shapefile driver, and GDAL options

Viewed 1332

In R, I have been successfully using the sf package, st_write function to write sf objects to shapefile, using the ESRI shapefile driver). I understand that the st_write function relies on GDAL.

I need to write shapefiles with several character class attributes in the df. These are all writing with a default 80 character width, as expected. I need to write these attributes to narrower field widths.

From the GDAL page:

Field sizes The driver knows to auto-extend string and integer fields (up to the 255 bytes limit imposed by the DBF format) to dynamically accommodate for the length of the data to be inserted.

It is also possible to force a resize of the fields to the optimal width by issuing a SQL ‘RESIZE ’ via the data source ExecuteSQL() method. This is convenient in situations where the default column width (80 characters for a string field) is bigger than necessary.

I need to do exactly this and force a resize, but I don't understand how to implement a SQL RESIZE<tablename> via the data source ExecuteSQL() method. I am not fluent (or experienced) with SQL and thus don't know where to begin in R.

Does anyone have an example of doing this in R? Can you point me in the right direction or provide an example?

1 Answers

I figured out the solution, pretty simple actually. Use the Layer_options within st_write

#load data
data(meuse,package="sp")

#create a character atribute with 10 characters
meuse$character<-"0123456789"

#convert to sf
meuse_sf = st_as_sf(meuse, coords = c("x", "y"), crs = 28992)

#drop extra attributes
final<-meuse_sf[,"character"]

#original problem, st_write to the esri driver
#would create a character field of length 80
st_write(final, paste0(getwd(), "/", "character_long.shp"))

#as per GDAL https://gdal.org/drivers/vector/shapefile.html#vector-shapefile
#LAYER CREATION OPTIONS
#RESIZE=YES/NO: set the YES to resize fields to their optimal size. 
#See above “Field sizes” section. Defaults to NO.

Layer_opt<-c("RESIZE=yes")
st_write(final,paste0(getwd(), "/", "character_RESIZE.shp"),layer_options = Layer_opt)
#this writes to a text field optimized to the contents (in this case 10)

Followup question, Is there a way to set the field to a specific length

Related