The census bureau doesn't provide a nationwide shapefile of public use microdata areas (the smallest geography available on the American Community Survey). I tried combining them all with a few different methods, but even the one that de-dupes identifiers breaks once it hits California. Am I doing something silly or does this require a difficult workaround? Here's code to reproduce up to the point where things break.
library(taRifx.geo)
library(maptools)
td <- tempdir() ; tf <- tempfile()
setInternet2( TRUE )
download.file( "ftp://ftp2.census.gov/geo/tiger/TIGER2014/PUMA/" , tf )
al <- readLines( tf )
tl <- al[ grep( "geo/tiger/TIGER2014/PUMA/tl_2014_" , al ) ]
fp <- gsub( "(.*)geo/tiger/TIGER2014/PUMA/tl_2014_([0-9]*)_puma10\\.zip(.*)" , "\\2" , tl )
# get rid of alaska
fp <- fp[ fp != '02' ]
af <- paste0( "ftp://ftp2.census.gov/geo/tiger/TIGER2014/PUMA/tl_2014_" , fp , "_puma10.zip" )
d <- NULL
for ( i in af ){
try( file.remove( z ) , silent = TRUE )
download.file( i , tf , mode = 'wb' )
z <- unzip( tf , exdir = td )
b <- readShapePoly( z[ grep( 'shp$' , z ) ] )
if ( is.null( d ) ) d <- b else d <- taRifx.geo:::rbind.SpatialPolygonsDataFrame( d , b , fix.duplicated.IDs = TRUE )
}
# Error in `row.names<-.data.frame`(`*tmp*`, value = c("d.0", "d.1", "d.2", :
# duplicate 'row.names' are not allowed
# In addition: Warning message:
# non-unique values when setting 'row.names': ‘d.0’, ‘d.1’, ‘d.10’, ‘d.11’, ‘d.12’, ‘d.13’, ‘d.14’, ‘d.15’, ‘d.16’, ‘d.17’, ‘d.18’, ‘d.19’, ‘d.2’, ‘d.3’, ‘d.4’, ‘d.5’, ‘d.6’, ‘d.7’, ‘d.8’, ‘d.9’
Here's another approach, which includes a short cut for obtaining the FTP directory listing. As @Pop mentioned, the key is to ensure that the IDs are all unique.
Your problem as you should have guessed is due to the fact that there are duplicate polygon IDs in your object
d
.Indeed, all the polygon IDs in your "shp" files are
"0"
. Thus, you usedfix.duplicated.IDs = TRUE
to make them different.This is weird because the
taRifx.geo:::rbind.SpatialPolygonsDataFrame
should have fixed it as you setfix.duplicated.IDs = TRUE
. More accurately, the information is transmitted tosp::rbind.SpatialPolygons
which calls the "internal" functionsp:::makeUniqueIDs
, which finally uses the functionbase::make.unique
.I did not want to see what went wrong in this chain. Alternatively, I advise you to set up yourself the IDs of your polygons, instead of using the
fix.duplicated.IDs
option.To fix it by yourself, replace your for-loop by the following code:
The simple for-loop on
j
only changes the ID of each polygon in the objectb
before biding it tod
.