16

I'm currently using the following script to add some attribute data from a table to lots of individual shapefiles:

library(rgdal)
specieslist <- read.csv("SpeciesList1.txt", header=F)
attdata <- read.table("TestAtt.csv", sep = ",", header=T)
for (n in 1:dim(specieslist)[1]) 
{
speciesname <- specieslist[n,1]
shp <- readOGR("Mesoamerica_modified_polygons", speciesname)
shp$ENGL_NAME<-attdata[n,2]
writeOGR(shp, "PolygonsV2", speciesname, driver="ESRI Shapefile")
}

I get the following warning(s) at the end:

1: In writeOGR(shp, "PolygonsV2", speciesname, driver = "ESRI Shapefile") :
Field names abbreviated for ESRI Shapefile driver

When viewing the attribute table of the shapefiles after this process, the Field name has been shortened to 'ENGL_', but I want it to stay as 'ENGL_NAME'. Is there a way to turn this abbreviating off?

Any help much appreciated.

  • Are any of the fieldnames in the shapefile > 10 characters? Looks like a bug in the R bindings to me. – geographika Aug 2 '12 at 12:04
  • 1
    Hi there, I just re-ran the script and now it isn't abbreviating. I'm not sure what's changed to cause this though... – JPD Aug 2 '12 at 12:27
6

You can't, it's a shapefile issue. See http://gdal.org/drv_shapefile.html under 'Creation Options'

  • so it is not an issue of writeOGR? Is it actually issue of the format? – Tomas Dec 2 '14 at 17:34
  • 1
    Correct. dbf column name lengths are limited. Another format, for example sqlite/spatialite would not truncate the names (there are very large limits in sqlite, but many orders of magnitude above 10). – user10353 Dec 4 '14 at 16:48
  • 3
    Well, there is a difference between normal abbreviation of column names when writing to dbf and what writeOGR is doing there! writeOGR is crippling even field names shorter than 10. My examples: My R-column name "ora_nachweis_id" becomes "or_nch_" while writeSpatilaPolygon does the normal abbreviation -> "ora_nachwe". Even my variable "LblColor" (8 characters !) becomes "LblColr". – Bernd V. Dec 4 '14 at 19:09
  • Are there similar column names in the db/data structure? I couldn't replicate with ogr2ogr and a sqlite db with those names. If you can provide a sample I could look further, or perhaps the R bindings are causing issues. – user10353 Jan 13 '15 at 22:14
  • 1
    Link is dead, but also, I have shapefiles with field names much longer than 10 characters; why is this possible if it's a shapefile issue? – Matt Mar 6 '17 at 17:55
7

Your 'ENGL_NAME' shouldn't be abbreviated at all (less than 10 characters), but writeOGR has its own will, it seems.

Instead of

writeOGR(shp, "PolygonsV2", speciesname, driver="ESRI Shapefile")

you might try

library(maptools)
currdir <- getwd() #store your current working directory
setwd(paste(currdir,"PolygonsV2",sep="/")) #switch to your desired folder

writeSpatialShape(shp, speciesname) # write shapefile

setwd(currdir) #switch back to parent folder

As writeSpatialShape seems not have a parameter for the destination, I found this workaround switching the working directory back and forth.

The other problem there is, that it does't produce a .prj-file, but thats a minor problem, compared to destroyed field names.

Waiting for the times when +*#-!(/ ESRI Shapefile format is finally dead and replaced by ... well?

  • Replaced by geopackage? – jsta Sep 25 '17 at 15:37
3

I've been having similar troubles working in RStudio. Per the advice in various comments and answers above, my scorched-earth solution is:

  • at the point where the SpatialWhateverDataFrame is ready to be written to Shape, make a copy
  • names(copy@data) <- c('new', 'short', 'names', 'you', 'pickd', 'yrslf')
  • names(copy@data) <- strtrim(names(copy@data), 10) just to be sure
  • writeOGR(copy, dsn, layer, driver = 'ESRI Shapefile') but don't run it yet
  • save the script, clear the workspace including hidden objects, restart R, rerun the entire script.

writeOGR() uses base::abbreviate - here's a test with a copy of lines 158-164:

fld_names <- c('short', 'longlonglong', 'middle_1')
if (any(nchar(fld_names) > 10)) {
    fld_names <- abbreviate(fld_names, minlength = 7)
    warning("Field names abbreviated for ESRI Shapefile driver")
    if (any(nchar(fld_names) > 10)) 
      fld_names <- abbreviate(fld_names, minlength = 5)
  }

> fld_names
       short longlonglong     middle_1 
     "short"    "lnglngl"    "middl_1" 
> names(fld_names)
[1] "short"        "longlonglong" "middle_1"  

You can see it actually calls abbreviate twice (possibly pointlessly, I can't figure out how you'd trigger that sub-loop), and if even one column name > 10 then it'll shorten any column name with > 7 characters. I cant figure out why one has to clear the workspace and restart if writeOGR has been run on the same object before, but maybe its something to do with fld_names being a named character vector. It might work better if as.character() was wrapped around abbreviate().

  • Hey, thanks. I didn't want to loose my PRJ file so reading this answer helped. I made ALL my field names 10 or less characters before calling writeOGR and none were abbreviated to 7. – Nova Dec 12 '16 at 18:42
-1

As already mentioned, shapefiles have a field name character limit of 10 characters. writeOGR meets this requirement by changing the field headings using some algorithm that prioritizes what characters to remove when there is a field name that exceeds the limit. I'm not sure how it works, but it seems to shorten field names in strange and unpredictable ways, and can shorten field names this way that already met the 10 requirement.

Here's my work around. Using strtrim() and setting the character length to 10 will truncate the field names to 10 characters more predictably than writeOGR's automation.

One issue that you might have is if you have fieldnames that are identical for the first 10 characters, but I rarely have this problem.

I apply this every time I export a shapefile, just in case.

library(sp)
library(rgdal)

table <- data.frame(X_Coordinates = runif(10)*1000, 
                    Y_Coordinates = runif(10)*1000, 
                    LongFieldNameForData = runif(10))

p <- SpatialPointsDataFrame(SpatialPoints(table), data = table)

names(p) <- strtrim(names(points),10)

writeOGR(p, "OutputDirectory", "Points", "ESRI Shapefile")

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.