R ggplot2 fusionner avec les données shapefile et csv pour remplir les polygones

nous produisons quotidiennement des cartes qui montrent un niveau calculé pour la température dans 30 zones distinctes de notre région, chaque zone est remplie avec une couleur différente selon le niveau. Cette cartes

enter image description here

maintenant je veux passer de génération de carte à R. j'ai téléchargé les limites provinciales et municipales (vous pouvez trouver limites pour toute L'Espagne ou ici sous-ensemble pour ma région) et a réussi à les tracer avec ggplot2 en suivant Hadley's!--12-->exemple.

je peux aussi produire un fichier ascii qui contient deux colonnes: identifier (CODINE) et niveau quotidien. Vous pouvez télécharger ici.

c'est mon premier script qui tente de tracer les shapefiles avec R et ggplot2 pour qu'il y ait des erreurs et pour être sûr qu'il peut être amélioré, les suggestions sont les bienvenues. Le code suivant (basé sur Hadley déjà cité) fonctionne pour moi:

> require("rgdal")
> require("maptools")
> require("ggplot2")
> require("plyr")

# Reading municipal boundaries

esp = readOGR(dsn=".", layer="lineas_limite_municipales_etrs89")

muni=subset(esp, esp$PROV1 == "46" | esp$PROV1 == "12" | esp$PROV1 == "3")
muni@data$id = rownames(muni@data)
muni.points = fortify(muni, region="id")
muni.df = join(muni.points, muni@data, by="id")

# Reading province boundaries

prov = readOGR(dsn=".", layer="poligonos_provincia_etrs89")

pr=subset(prov, prov$CODINE == "46" | prov$CODINE == "12" | prov$CODINE == "03" )
pr@data$id = rownames(pr@data)
pr.points = fortify(pr, region="id")
pr.df = join(pr.points, pr@data, by="id")

ggplot(muni.df) + aes(long,lat,group=group) + geom_path(color="blue") +
+ coord_equal()+ geom_path(data=pr.df, + 
aes(x=long, y=lat, group=group),color="red", size=0.5) 

ce code trace une belle carte avec toutes les limites enter image description here

pour le remplissage des polygones par niveau j'ai essayé de lire puis de fusionner comme suggéré dans http://tormodboe.wordpress.com/2011/02/22/g%C3%B8y-med-kart-2/

niveau=lire.csv("niveaux.dat", header=T, sep="")

munlevel=merge (muni.DF, level, by= "CODINE")

mais il donne une erreur

Erreur fr fix.by(par.x, x) : "par" doit spécifier un unique valide la colonne

Je ne suis pas familier avec les shapefiles, peut-être que j'ai besoin d'en savoir plus sur les attributs de données shp pour trouver le bon choix de fusionner les deux ensembles de données. Comment puis-je fusionner les données pour tracer les lignes (limites municipales) et ensuite les remplir avec des niveaux?

9
demandé sur Bart 2013-11-05 18:23:29

1 réponses

[NB: cette question a été posée il y a plus d'un mois donc OP a probablement trouvé une autre façon de résoudre leur problème. Je suis tombé sur elle tout en travaillant sur cette question connexe. Cette réponse est incluse dans l'espoir qu'elle profitera à quelqu'un d'autre.]

il semble que C'est ce que L'OP demande...

... et a été produit avec le suivant code:

require("rgdal")
require("maptools")
require("ggplot2")
require("plyr")

# read temperature data
setwd("<location if your data file>")
temp.data        <- read.csv(file = "levels.dat", header=TRUE, sep=" ", na.string="NA", dec=".", strip.white=TRUE)
temp.data$CODINE <- str_pad(temp.data$CODINE, width = 5, side = 'left', pad = '0')

# read municipality polygons
setwd("<location of your shapefile")
esp     <- readOGR(dsn=".", layer="poligonos_municipio_etrs89")
muni    <- subset(esp, esp$PROVINCIA == "46" | esp$PROVINCIA == "12" | esp$PROVINCIA == "3")
# fortify and merge: muni.df is used in ggplot
muni@data$id <- rownames(muni@data)
muni.df <- fortify(muni)
muni.df <- join(muni.df, muni@data, by="id")
muni.df <- merge(muni.df, temp.data, by.x="CODIGOINE", by.y="CODINE", all.x=T, a..ly=F)
# create the map layers
ggp <- ggplot(data=muni.df, aes(x=long, y=lat, group=group)) 
ggp <- ggp + geom_polygon(aes(fill=LEVEL))         # draw polygons
ggp <- ggp + geom_path(color="grey", linestyle=2)  # draw boundaries
ggp <- ggp + coord_equal() 
ggp <- ggp + scale_fill_gradient(low = "#ffffcc", high = "#ff4444", 
                                 space = "Lab", na.value = "grey50",
                                 guide = "colourbar")
ggp <- ggp + labs(title="Temperature Levels: Comunitat Valenciana")
# render the map
print(ggp)

Explication:

les fichiers de formes importées dans R readOGR(...) sont de type SpacialDataFrame et de deux sections principales: ploygon section qui contient les coordonnées de tous les points sur chaque polygone, et un section qui contient des informations sur chaque polygone (donc, une ligne par polygone). Ceux-ci peuvent être référencés, par exemple, en utilisant muni@polygons et muni@data. La fonction utilitaire fortify(...) convertit le section polygone à une base de données organisée pour tracer avec ggplot. Le workflow de base est donc:

[1] Import temperature data file (temp.data)
[2] Import polygon shapefile of municipalities (muni)
[3] Convert muni polygons to a data frame for plotting (muni.df <- fortify(...))
[4] Join columns from muni@data to muni.df
[5] Join columns from temp.data to muni.df
[6] Make the plot

Le joint doit être fait sur les champs communs, et c'est là que la plupart des problèmes viennent. Chaque polygone du shapefile original possède un attribut ID unique. Cours d'exécution fortify(...) sur le shapefile crée une colonne, id, qui est basé sur ceci. Mais il n'y a pas de colonne ID dans la section Données. Au lieu de cela, les ID polygones sont stockés sous forme de noms de lignes. Nous devons donc d'abord ajouter un id colonne muni@data comme suit:

muni@data$id <- rownames(muni@data)

Maintenant, nous avons un id champ muni@data et id champ muni.df, afin que nous puissions faire la jointure:

muni.df <- join(muni.df, muni@data, by="id")

Pour créer la carte, nous aurons besoin de définir les couleurs de remplissage en fonction de la température. Pour ce faire, nous devons rejoindre le LEVEL colonne temp.datamuni.df. temp.data il y a un champ CODINE qui identifie la municipalité. Il y a aussi, maintenant, un champ correspondant CODIGOINE muni.df. Mais il y a un problème: CODIGOINEchar(5), avec des zéros en tête, alors que CODINE est entier ce qui signifie que les zéros de tête sont manquants (importés D'Excel, peut-être?). Le simple fait de se joindre à ces deux groupes ne produit aucune correspondance. Il faut d'abord convertir CODINE en char(5) avec les zéros non significatifs:

temp.data$CODINE <- str_pad(temp.data$CODINE, width = 5, side = 'left', pad = '0')

Maintenant on peut se joindre à temp.datmuni.df basé sur les champs correspondants.

muni.df <- merge(muni.df, temp.data, by.x="CODIGOINE", by.y="CODINE", all.x=T, a..ly=F)

Nous utilisons merge(...) au lieu de join(...) parce que les champs de jointure ont des noms différents et join(...) exige qu'ils aient le même nom. (Notez, cependant, que join(...) est plus rapide et devrait être utilisé si possible). Donc, finalement, nous avons une base de données qui contient toutes les informations pour tracer les polygones et la température LEVEL qui peut être utilisé pour définir la couleur de remplissage pour chaque polygone.

Quelques notes sur les OP le code original:

  1. la première carte de L'OP (la verte en haut) identifie " 30 zones distinctes pour notre région...". Je n'ai pas trouvé de shapefile identifiant ces zones. Le dossier des municipalités recense 543 municipalités, et je ne vois aucun moyen de les regrouper en 30 secteurs. De plus, le fichier des niveaux de température comporte 542 lignes, une pour chaque municipalité (plus ou moins).

  2. OP importait des shapefiles de ligne pour que la municipalité trace les limites. Vous n'en avez pas besoin car geom_polygon(...) va dessiner (et remplir) les polygones et geom_path(...) va tracer les limites.

16
répondu jlhoward 2013-12-09 21:25:37