from R-help digest, Vol 51, Issue 5 (5/5/2007) ------------------------------ Message: 74 Date: Sat, 5 May 2007 01:00:16 +0000 From: Alberto Vieira Ferreira Monteiro Subject: Re: [R] Help with map To: Roger.Bivand@nhh.no Cc: R-help@stat.math.ethz.ch Message-ID: <200705050100.18512.albmont@centroin.com.br> Content-Type: text/plain; charset="iso-8859-1" [for those that worry about these things, this _is_ a homework assignment. However, it's not an R homework, it's a Geography and History homework... and I want to use R to create a pretty map] Roger Bivand wrote: Is there any way to associate one color to each country? Try: map_poly_obj <- map("worldHires", c("Argentina", "Brazil"), plot=FALSE, fill=TRUE) str(map_poly_obj) and you'll see that the component of interest is the named polygons, of which there are 28, namely Ok, I guess I can see what you mean. It worked, but I don't think this is a practical way to draw things. For example, suppose [this would help homework mentioned above] I want to draw a series of maps showing the evolution of Communism in the XX century. I would like to start with a 1917 map, showing most countries as in... map("worldHires") .... but with the Soviet Union in red. I don't see how I could mix the two maps (BTW, there's no Russia in worldHires, but there is a USSR...) map("worldHires"); map("worldHires", "USSR", col="red", fill=T) map_poly_obj$names So you can build a matching colours vector, or: library(sp) library(maptools) IDs <- sapply(strsplit(map_poly_obj$names, ":"), function(x) x[1]) SP_AB <- map2SpatialPolygons(map_poly_obj, IDs=IDs, proj4string=CRS("+proj=longlat +datum=wgs84")) but plot(SP_AB, col=c("cyan", "green")) still misses, because some polygons have their rings of coordinates in counter-clockwise order, so: pl_new <- lapply(slot(SP_AB, "polygons"), checkPolygonsHoles) slot(SP_AB, "polygons") <- pl_new # please forget the assignment to the slot and do not do it unless you can # replace what was there before plot(SP_AB, col=c("cyan", "green"), axes=TRUE) now works. Moreover, SP_AB is a SpatialPolygons object, which can be promoted to a SpatialPolygonsDataFrame object, for a data slot holding a data.frame with row names matching the Polygons ID values: sapply(slot(SP_AB, "polygons"), function(x) slot(x, "ID")) So adding a suitable data frame gets you to the lattice graphics method spplot(SP_AB, "my_var") Hope this helps, So, in the above mentioned case, I could do something like: library(mapdata) commies <- c("USSR", "Mongolia") # Mongolia was the 2nd communist country, in 1925 map_poly_obj <- map("worldHires", plot=FALSE) map_poly_commies <- map("worldHires", commies, plot=FALSE, fill=TRUE) plot(map_poly_obj, type="l") polygon(map_poly_commies, col="red", border="black") I guess I can keep going, unless there is a simpler solution. Alberto Monteiro ------------------------------------------------------------------------------ Here's the sloppy code I used to put together the map in the persp3d example in rgl 0.71. I've just made a few edits; I hope it still runs. The idea is to do a lot of calculations on a vector of colours, then plot them all at once. library(mapdata) names <- map("worldHires", plot=FALSE, namesonly=TRUE) countries <- gsub(":.*", "", names) # the first part of the name lakes <- grep("Lake", names) lakes <- lakes[-15] lakes <- unique(c(lakes, grep("Ozero", names), grep("Vodokh", names), grep("Nuur", names), grep("Ostrov Ol'khon", names), grep("Hayk", names), grep("Lago", names))) # The map doesn't distinguish these seas <- grep("Sea", names) nfld <- grep("^Newfoundland$", names) # nfld should be coloured as Canada canada <- grep("^Canada$", names) svalbard <- grep("Svalbard", names) # Svalbard coloured as Norway norway <- grep("^Norway$", names) nums <- as.numeric(factor(countries)) N <- max(nums) set.seed(3) col <- hcl(h=sample((1:N)*360/N), c=sample(seq(35,45,len=N)), l=sample(seq(75,85,len=N)))[nums] # random colours by country col[c(lakes,seas)] <- "white" # with lakes and seas white col[nfld] <- col[canada] col[svalbard] <- col[norway] png(width=2200, height=2200, file='world.png') map('worldHires', fill = TRUE, col = col, ylim=c(-90,90)) abline(h=c(-90, 90)) abline(v=c(-180.05, 180.05)) dev.off() I hope this gives you some ideas. Duncan Murdoch ------------------------------------------------------------------------------ [Please note that the worldHires database refers to a particular time cross section, probably late 1980's. The territorial extents of the former USSR in 1919, 1920, 1939, 1940, 1941, 1944, 1945, etc., etc. are not the same; the same consideration would apply to PRC's actual control over Tibet. So to do this, you need a sequence of maps showing the marginal increments, with 1917 actually only colouring Petrograd/St Petersburg and perhaps some other cities. I'm not aware of any publically available sequence of boundary files adequately representing the situation of say the Baltic states or Finland for the 1917-2007 period, if anyone has a suitable link, please say so. Geographical data are vintaged, not just "where", but "where when". Was for example Estonia occupied by the USSR 1940-1941, 1944-1991, or was it part of the USSR for the purposes of this exercise? Using disputed boundaries implies a choice of point of view, one that may not be intended.] Roger