2013-08-28 2 views
1

J'utilise ggplot2 pour créer une densité de population choroplèthe. Il fonctionne actuellement pour les états uniques, mais pas pour les multiples. Il semble que les densités de divers comtés (qui ont souvent le même nom) se confondent, et parfois même les comtés non-appariés sont mélangés entre les états. Par exemple, "New Jersey" donne les densités correctes, mais "New Jersey", "New York" me dit que le très peuplé comté d'Essex dans le New Jersey a une densité < 30p/mi^2. Pourquoi est-ce?Les comtés sont brouillés en R

library(stringr) 
library(ggplot2) 
library(scales) 
library(maps) 

popdensitymap <- function(...){ 
path <- "U:/maps-county2011.csv" 

states <- list(...) 
countydata <- read.csv(path, sep=",") 

countydata <- data.frame(countydata$X, countydata$Population.Density) 
names(countydata) <- c("fips", "density") 

data(county.fips) 

cdata <- countydata 
cdata$fips <- gsub("^0", "", cdata$fips) 
countyinfo <- merge(cdata, county.fips, by.x="fips", by.y="fips") 

countyinfo <- data.frame(countyinfo, str_split_fixed(countyinfo$polyname, ",", 2)) 
names(countyinfo) <- c('fips', 'density', 'polyname', 'state', 'county') 
countyshapes <- map_data("county", states) 
countyshapes <- merge(countyshapes, countyinfo, by.x="subregion", by.y="county") 
choropleth <- countyshapes 
choropleth <- choropleth[order(choropleth$order), ] 
choropleth$density_d <- cut(choropleth$density, breaks=c(0,30,100,300,500,1000,3000,5000,100000)) 

state_df <- map_data("state", states) 
density_d <- choropleth$density_d 
choropleth <- choropleth[choropleth$state %in% tolower(states),] 


p <- ggplot(choropleth, aes(long, lat, group=group)) 
p <- p + geom_polygon(aes(fill=density_d), colour=alpha("white", 1/2), size=0.2) 
p <- p + geom_polygon(data = state_df, colour="black", fill = NA) 
p <- p + scale_fill_brewer(palette="PuRd") 
p 
} 

Pour utiliser,

popdensitymap("New Jersey") 
popdensitymap("New York", "New Jersey") 

Here is the csv. Il est très laid, mais je ne pas avoir accès à un système de partage de fichiers en ce moment.

Voici un exemple de sortie. Comme vous pouvez le voir, le très peuplé comté d'Essex par New York City est inexactement représenté. enter image description here

EDIT: Here is my version of the CSV. Désolé pour le délai de dépôt.

+0

Votre fichier csv ne se lit pas correctement. Il semble avoir un titre d'en-tête (?!) Et même si cela est supprimé, les noms de champs sont incorrects. – geotheory

+0

@geotheory c'est étrange, ça marche bien pour moi. J'ai tout supprimé jusqu'à la ligne ,,,, 2010,2011, Nombre, Pourcentage, Nombre, Pourcentage, Densité de la Population, Zone (Milles Carrés) ,,,,, et les lignes en bas. –

+0

Non reproductible. Si je copie, colle et fonctionne avec 'popdensitymap (" New Jersey ")' I get 'Erreur dans les données.frame (countydata $ X, countydata $ Population.Density): arguments impliquent un nombre différent de lignes: 3284, 0'. D'une part, il semble qu'il y ait une faute de frappe dans votre argument 'breaks' à' cut', la dernière valeur devrait être '10000' et non' 100000'? Par intérêt, le code fonctionne-t-il si vous le supprimez de la fonction? J'ai mis en place un choroplèthe pour vérifier et les données de population et les polygones de carte sont bien, c'est donc définitivement votre code. – SlowLearner

Répondre

0

D'accord, je l'ai eu. SlowLearner et Shujaa m'ont fait réaliser que le problème était que les comtés dans différents états avec les mêmes noms ne se voyaient pas attribuer les bonnes densités de population.

Pour contrer cela, la fusion se fait maintenant par polyname, ce qui signifie le polyname en countyinfo n'a pas besoin d'être changé et un polyname est ajouté à countyshapes comme ceci:

countyshapes$polyname <- paste(countyshapes$region, countyshapes$subregion, sep=",") 

Merci pour l'aide. Je ne sais pas si je devrais supprimer la question ou la laisser pour référence.

+1

Je le quitterais. Bien que, pour être honnête, j'ai trouvé la question assez compliquée à traiter, «fusionner» dans le contexte des tâches SIG génère des problèmes pour les gens et la réponse pourrait bien aider quelqu'un d'autre. Merci d'avoir posté votre réponse. – SlowLearner

1

Juste pour démontrer qu'un exemple plus simple semble fonctionner ...

new jersey

library(ggplot2) 
library(scales) 
library(maps) 

csv.file <- "http://www.census.gov/popest/data/maps/2011/maps-county2011.csv" 

mydf <- read.csv(csv.file, skip = 4, header = TRUE, check.names = FALSE) 
mydf <- mydf[, c(1, 2, 5, 10, 11)] # we can drop most columns 

colnames(mydf) <- c("code", "subregion", "population", "density", "area") 
mydf$population <- as.numeric(gsub(",", "", mydf$population)) # remove commas 
mydf$area <- as.numeric(gsub(",", "", mydf$area)) # remove commas 

nj.pop <- mydf[substr(mydf$code, 1, 3) == '340', ] # new jersey code is 34000 
nj.pop <- nj.pop[2:nrow(nj.pop), ] # drop first row i.e. new jersey state itself 
nj.pop$subregion <- tolower(gsub(" County", "", nj.pop$subregion)) 
nj.pop$subregion <- gsub("\\.", "", nj.pop$subregion) 
nj.pop$density_d <- cut(nj.pop$density, 
         breaks = c(0,30,100,300,500,1000,3000,5000,100000), 
         dig.lab = 6, include.lowest = TRUE) 

nj.pop 

nj.shp <- map_data("county") # grab... 
nj.shp <- nj.shp[nj.shp$region == 'new jersey', ] # ...and subset 

identical(unique(nj.shp2$subregion), unique(nj.pop$subregion)) # should be TRUE 

nj.both <- merge(nj.pop, nj.shp2, by = "subregion") 

p <- ggplot(nj.both, aes(long, lat, group = group)) + 
    geom_polygon(aes(fill = density_d), colour = alpha("white", 1/2), 
       size = 0.2) + 
    scale_fill_brewer(palette = "PuRd") + 
    coord_equal() 

print(p) 
+0

Exactement. Les exemples à un seul état fonctionnent. Le problème se produit lorsque plusieurs états sont utilisés. Je vais essayer 'sort = FALSE' comme vous l'avez suggéré ci-dessous. –

+0

Je pense que le problème pourrait provenir de la fusion. La fusion par «sous-région» seule avec plusieurs états avec des noms de comté répétés peut être source de confusion et affecter la même densité à des comtés avec les mêmes noms car elle ne sait pas à quelle région appartient chaque sous-région. Existe-t-il un moyen de fusionner avec plusieurs critères? Je suppose que l'utilisation de données fips empêcherait cela, mais comment ajouter des numéros de fips à 'map_data' sans rencontrer le même problème? –

1

J'ai eu des problèmes similaires faire des cartes et en utilisant merge, parce que merge ne conserve pas nécessairement l'ordre des lignes dans le premier data.frame. Ma solution a été d'utiliser plyr::join à la place (qui a aussi tendance à être plus rapide).

Le seul inconvénient est les colonnes que vous rejoignez sur besoin d'avoir les mêmes noms dans les deux cadres de données. De ?join:

Contrairement à la fusion, [rejoindre] conserve l'ordre de x, peu importe ce type de jointure utilisé. Si nécessaire, les lignes de y seront ajoutées en bas. Join est souvent plus rapide que la fusion, bien qu'il soit un peu moins riche en fonctionnalités - il ne propose actuellement aucun moyen de renommer la sortie ou de fusionner sur différentes variables dans les trames de données x et y.

+0

'merge' avec' sort = FALSE' peut parfois corriger ce genre de [problème] (http://gis.stackexchange.com/questions/37204/quand-est-ce-que-cause-de-learning-des-polygons- artefacts-using-r-ggplot-and-geom). – SlowLearner

Questions connexes