An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/9404fd76/attachment.pl>
How to extract coordinates values from a shapefile?
16 messages · Henrique Dallazuanna, Nikhil Kaza, Thiago V. dos Santos +5 more
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/f0149314/attachment.pl>
Look at this. Not sure if this is indeed what you want or if you actually have to unproject them. http://www.mail-archive.com/r-sig-geo at stat.math.ethz.ch/msg04715.html require(ggplot2) fortify(br) Nikhil Kaza Asst. Professor, City and Regional Planning University of North Carolina nikhil.list at gmail.com
On Jun 9, 2010, at 2:45 PM, Thiago Veloso wrote:
Dear R colleagues,
Does anyone know if it's possible to create a vector with
coordinate values extracted from a shape loaded with readShapePoly
command of "maptools" package?
For example, the following code loads the shapefile containing
Brazilian states division:
library(maptools)br<-readShapePoly("BR-map/3.shp")
What I need to do is create a vector which contains all lat and
lon values inside this shapefile...
Thanks in advance,
Thiago Veloso.
[[alternative HTML version deleted]]
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at stat.math.ethz.ch https://stat.ethz.ch/mailman/listinfo/r-sig-geo
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/4dbc8eb9/attachment.pl>
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/d6ecd153/attachment.pl>
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/92104c29/attachment.pl>
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/f3059a15/attachment.pl>
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100609/dcb54116/attachment.pl>
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx <- readShapePoly(system.file("shapes/sids.shp", package="maptools")[1],
IDvar="FIPSNO", proj4string=CRS("+proj=longlat +ellps=clrk66"))
allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
On 06/09/2010 09:58 PM, Matt Beard wrote:
library(maptools)
# A simple way to print out a list of coordinates for each polygon in your
shapefile:
# Path and filename of polygon shapefile
testfile <- '/media/PKBACK# 001/FNR210/QGISLab/habitats/habitats.shp'
# Read in polygon shapefile using handy maptools function
test <- readShapePoly(testfile)
# Extract the list of Polygons objects
polys <- slot(test,"polygons")
# Within each Polygons object
# Extract the Polygon list (assuming just one per Polygons)
# And Extract the coordinates from each Polygon
for (i in 1:length(polys)) {
print(paste("Polygon #",i))
print(slot(slot(polys[[i]],"Polygons")[[1]],"coords" ))
}
[[alternative HTML version deleted]]
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at stat.math.ethz.ch https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Edzer Pebesma Institute for Geoinformatics (ifgi), University of M?nster Weseler Stra?e 253, 48151 M?nster, Germany. Phone: +49 251 8333081, Fax: +49 251 8339763 http://ifgi.uni-muenster.de http://www.52north.org/geostatistics e.pebesma at wwu.de
On Wed, Jun 9, 2010 at 3:24 PM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de> wrote:
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx <- readShapePoly(system.file("shapes/sids.shp", package="maptools")[1],
?IDvar="FIPSNO", proj4string=CRS("+proj=longlat +ellps=clrk66"))
allcoordinates = function(x) {
? ?ret = NULL
? ?polys = x at polygons
? ?for(i in 1:length(polys)) {
? ? ? ?pp = polys[[i]]@Polygons
? ? ? ?for (j in 1:length(pp))
? ? ? ? ? ?ret = rbind(ret, coordinates(pp[[j]]))
? ?}
? ?ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
And that's basically what fortify does, except it covers a few more cases. Hadley
Assistant Professor / Dobelman Family Junior Chair Department of Statistics / Rice University http://had.co.nz/
On Wednesday 09 June 2010, Hadley Wickham wrote:
On Wed, Jun 9, 2010 at 3:24 PM, Edzer Pebesma <edzer.pebesma at uni-muenster.de> wrote:
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx <- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66")) allcoordinates = function(x) {
? ?ret = NULL
? ?polys = x at polygons
? ?for(i in 1:length(polys)) {
? ? ? ?pp = polys[[i]]@Polygons
? ? ? ?for (j in 1:length(pp))
? ? ? ? ? ?ret = rbind(ret, coordinates(pp[[j]]))
? ?}
? ?ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
And that's basically what fortify does, except it covers a few more cases. Hadley
Not to be nit-picky, but wouldn't it be safer to pre-allocated "ret" instead of dynamically appending? This would allow the suggested function to scale to very large geometries. Cheers, Dylan
Dylan Beaudette Soil Resource Laboratory http://casoilresource.lawr.ucdavis.edu/ University of California at Davis 530.754.7341
On 06/09/2010 11:01 PM, Dylan Beaudette wrote:
On Wednesday 09 June 2010, Hadley Wickham wrote:
On Wed, Jun 9, 2010 at 3:24 PM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de> wrote:
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx<- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66")) allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
And that's basically what fortify does, except it covers a few more cases.
Hadley
Not to be nit-picky, but wouldn't it be safer to pre-allocated "ret" instead of dynamically appending? This would allow the suggested function to scale to very large geometries.
A combination of lapply and do.call("rbind" also works well in terms of
performance.
cheers,
Paul
Cheers, Dylan
Drs. Paul Hiemstra Department of Physical Geography Faculty of Geosciences University of Utrecht Heidelberglaan 2 P.O. Box 80.115 3508 TC Utrecht Phone: +3130 274 3113 Mon-Tue Phone: +3130 253 5773 Wed-Fri http://intamap.geo.uu.nl/~paul http://nl.linkedin.com/pub/paul-hiemstra/20/30b/770
On 06/09/2010 11:01 PM, Dylan Beaudette wrote:
On Wednesday 09 June 2010, Hadley Wickham wrote:
On Wed, Jun 9, 2010 at 3:24 PM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de> wrote:
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx<- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66")) allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
And that's basically what fortify does, except it covers a few more cases.
Hadley
Not to be nit-picky, but wouldn't it be safer to pre-allocated "ret" instead of dynamically appending? This would allow the suggested function to scale to very large geometries.
In addition to my previous suggestion, I tried using lapply + do.call
instead of the for loop based implementation of edzer:
library(maptools)
xx<- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66"))
allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
allcoordinates_lapply = function(x) {
polys = x at polygons
return(do.call("rbind", lapply(polys, function(pp) {
do.call("rbind", lapply(pp at Polygons, coordinates))
})))
}
q = allcoordinates(xx)
z = allcoordinates_lapply(xx)
all.equal(q,z)
So far it produces the same output. And now comes the nice part, doing a
test with a large polygon set and timing the performance of both functions:
> system.time(x <- allcoordinates(nuts))
user system elapsed
22.781 8.572 31.422
> system.time(y <- allcoordinates_lapply(nuts))
user system elapsed
0.248 0.004 0.250
> all.equal(x,y)
[1] TRUE
So apart from the imo nicer looking function in terms of syntax, it is
also several orders of magnitude faster. This effect will only become
stronger if the polygon set becomes larger. So, lapply + do.call is your
friend :).
cheers,
Paul
> sessionInfo()
R version 2.11.0 (2010-04-22)
i486-pc-linux-gnu
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=C LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] maptools_0.7-34 lattice_0.18-5 sp_0.9-62 foreign_0.8-40
loaded via a namespace (and not attached):
[1] grid_2.11.0
Cheers, Dylan
Drs. Paul Hiemstra Department of Physical Geography Faculty of Geosciences University of Utrecht Heidelberglaan 2 P.O. Box 80.115 3508 TC Utrecht Phone: +3130 274 3113 Mon-Tue Phone: +3130 253 5773 Wed-Fri http://intamap.geo.uu.nl/~paul http://nl.linkedin.com/pub/paul-hiemstra/20/30b/770
1 day later
On 06/11/2010 11:43 AM, Paul Hiemstra wrote:
On 06/09/2010 11:01 PM, Dylan Beaudette wrote:
On Wednesday 09 June 2010, Hadley Wickham wrote:
On Wed, Jun 9, 2010 at 3:24 PM, Edzer Pebesma <edzer.pebesma at uni-muenster.de> wrote:
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's
sake, I
avoided nested sapply's.
library(maptools)
xx<- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66")) allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
And that's basically what fortify does, except it covers a few more cases. Hadley
Not to be nit-picky, but wouldn't it be safer to pre-allocated "ret" instead of dynamically appending? This would allow the suggested function to scale to very large geometries.
In addition to my previous suggestion, I tried using lapply + do.call
instead of the for loop based implementation of edzer:
library(maptools)
xx<- readShapePoly(system.file("shapes/sids.shp",
package="maptools")[1], IDvar="FIPSNO", proj4string=CRS("+proj=longlat
+ellps=clrk66"))
allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
allcoordinates_lapply = function(x) {
polys = x at polygons
return(do.call("rbind", lapply(polys, function(pp) {
do.call("rbind", lapply(pp at Polygons, coordinates))
})))
}
More information on why this is so much faster can be found in the R Inferno Chapter 2, this gives a good description of what goes wrong in the background when growing an R object. http://www.burns-stat.com/pages/Tutor/R_inferno.pdf The following basic R code also provides some info: # Just letting the object grow # without preallocation meth1 = function(n) { vec <- numeric(0); for(i in 1:n) vec <- c(vec, i) } # preallocation meth2 = function(n) { vec <- numeric(n) for(i in 1:n) vec[i] <- i } # Direct creation # Not relevant for the # above case meth3 = function(n) { vec <- 1:n } # The suggestion I did # with do.call and lapply meth4 = function(n) { do.call("c", lapply(1:n, function(x) x)) } n = 100000 # Speed test system.time(meth1(n)) # Slooooow system.time(meth2(n)) system.time(meth3(n)) system.time(meth4(n)) cheers, Paul
q = allcoordinates(xx) z = allcoordinates_lapply(xx) all.equal(q,z) So far it produces the same output. And now comes the nice part, doing a test with a large polygon set and timing the performance of both functions:
system.time(x <- allcoordinates(nuts))
user system elapsed 22.781 8.572 31.422
system.time(y <- allcoordinates_lapply(nuts))
user system elapsed 0.248 0.004 0.250
all.equal(x,y)
[1] TRUE So apart from the imo nicer looking function in terms of syntax, it is also several orders of magnitude faster. This effect will only become stronger if the polygon set becomes larger. So, lapply + do.call is your friend :). cheers, Paul
sessionInfo()
R version 2.11.0 (2010-04-22) i486-pc-linux-gnu locale: [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 [5] LC_MONETARY=C LC_MESSAGES=en_US.UTF-8 [7] LC_PAPER=en_US.UTF-8 LC_NAME=C [9] LC_ADDRESS=C LC_TELEPHONE=C [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] maptools_0.7-34 lattice_0.18-5 sp_0.9-62 foreign_0.8-40 loaded via a namespace (and not attached): [1] grid_2.11.0
Cheers, Dylan
Drs. Paul Hiemstra Department of Physical Geography Faculty of Geosciences University of Utrecht Heidelberglaan 2 P.O. Box 80.115 3508 TC Utrecht Phone: +3130 274 3113 Mon-Tue Phone: +3130 253 5773 Wed-Fri http://intamap.geo.uu.nl/~paul http://nl.linkedin.com/pub/paul-hiemstra/20/30b/770
1 day later
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-sig-geo/attachments/20100613/1e2f59c3/attachment.pl>
long = q[,1] lat = q[,2]
On 06/14/2010 05:05 AM, Thiago Veloso wrote:
This function worked like a charm, but I can't individually invoke the columns which contain the coordinates of variable "q".
names(q)NULL
For example, I need to plot the coordinates using polygon function, whose help tells us that "?polygon? draws the polygons whose vertices are given in ?x? and ?y?".
So, I'd like to be able to refer to lon and lat columns of variable "q" as "q$lon" and "q$lat".
Is it possible??
Best wishes,
Thiago.
--- On Wed, 9/6/10, Edzer Pebesma <edzer.pebesma at uni-muenster.de> wrote:
From: Edzer Pebesma <edzer.pebesma at uni-muenster.de>
Subject: Re: [R-sig-Geo] How to extract coordinates values from a shapefile?
To: r-sig-geo at stat.math.ethz.ch
Date: Wednesday, 9 June, 2010, 17:24
The example provided by Matt assumes that each polygon consists of a
single ring, and doesn't have islands, lakes etc. The function below
pasts all coordinates to a single 2-column matrix. For clarity's sake, I
avoided nested sapply's.
library(maptools)
xx <- readShapePoly(system.file("shapes/sids.shp", package="maptools")[1],
IDvar="FIPSNO", proj4string=CRS("+proj=longlat +ellps=clrk66"))
allcoordinates = function(x) {
ret = NULL
polys = x at polygons
for(i in 1:length(polys)) {
pp = polys[[i]]@Polygons
for (j in 1:length(pp))
ret = rbind(ret, coordinates(pp[[j]]))
}
ret
}
q = allcoordinates(xx)
# check:
plot(xx)
lines(q, col='blue')
On 06/09/2010 09:58 PM, Matt Beard wrote:
library(maptools)
# A simple way to print out a list of coordinates for each polygon in your
shapefile:
# Path and filename of polygon shapefile
testfile <- '/media/PKBACK# 001/FNR210/QGISLab/habitats/habitats.shp'
# Read in polygon shapefile using handy maptools function
test <- readShapePoly(testfile)
# Extract the list of Polygons objects
polys <- slot(test,"polygons")
# Within each Polygons object
# Extract the Polygon list (assuming just one per Polygons)
# And Extract the coordinates from each Polygon
for (i in 1:length(polys)) {
print(paste("Polygon #",i))
print(slot(slot(polys[[i]],"Polygons")[[1]],"coords" ))
}
[[alternative HTML version deleted]]
_______________________________________________ R-sig-Geo mailing list R-sig-Geo at stat.math.ethz.ch https://stat.ethz.ch/mailman/listinfo/r-sig-geo
Edzer Pebesma Institute for Geoinformatics (ifgi), University of M?nster Weseler Stra?e 253, 48151 M?nster, Germany. Phone: +49 251 8333081, Fax: +49 251 8339763 http://ifgi.uni-muenster.de http://www.52north.org/geostatistics e.pebesma at wwu.de