Искажение многоугольника, взвешенное по населению (картограммы)

Я пытаюсь создать карту в R, которая передает как форму базовой геометрии (т. е. физические границы), и относительную важность объекта с точки зрения связанного значения.

Для конкретики я хотел бы сосредоточиться на воспроизведении (версии) следующей карты* (формы, а не столько цвета, поскольку я не могу найти данные опроса):

 Искаженная карта Соединенных Штатов под названием Карта коллегии выборщиков 2012 года с подзаголовком Размер каждого штата искажен, чтобы подчеркнуть его долю голосов выборщиков. Штаты окрашены в красный или синий цвет в зависимости от того, проголосовал ли этот штат за Митта Ромни или Барака Обаму.  в 2012 году соответственно. Легенда отмечает это, а также общее количество голосов выборщиков (277 за Обаму, 261 за Ромни) и примечание о том, что для победы требуется 270 голосов выборщиков».  /></а></p>
<p>Я также не хочу беспокоиться о том, чтобы Аляска и Гавайи отображались ниже США, а не в их геодезически правильном местоположении.</p>
<p>Я только что объединил данные с весами, например, следующим образом:</p>
<h1>1. Получить полигоны</h1>
<pre><code>library(maptools)
library(data.table) #not strictly necessary but I prefer it
#US states downloaded (500k resolution) from:
#https://www.census.gov/geo/maps-data/data/cbf/cbf_state.html
us.states<-
  readShapePoly("~/Desktop/cb_2014_us_state_5m.shp")

setDT(us.states@data)

#for getting rid of territories, AK, HI
states<-sprintf("%02d",1:59)
ak.hi<-c("02","15")

us.states.contig<-
  us.states[us.states@data$STATEFP %in% 
              setdiff(states,ak.hi),]

#Unadorned plot
plot(us.states.contig)
text(coordinates(us.states.contig),
     us.states.contig@data[,paste0(STUSPS)],
     cex=.7)
</code></pre>
<p><a href=Простая, неискаженная карта континентальной части Соединенных Штатов. Белые многоугольники, черные границы, аннотации с двухбуквенными почтовыми индексами штатов.

2. Добавьте данные Коллегии выборщиков

#scraped from government page
library(rvest) #only necessary to scrape table
electoral.college.url<-
  paste0("http://www.archives.gov/federal-register/",
         "electoral-college/allocation.html")

electoral.college.dt<-
  (html(electoral.college.url) %>%
     html_nodes("table"))[[5]] %>% 
  html_table()
setDT(electoral.college.dt)
setnames(electoral.college.dt,c("State","Votes"))

#merge into geodata
us.states.contig@data<-
  copy(us.states.contig@data)[
    electoral.college.dt,electoral.votes:=i.Votes,
    on=c(NAME="State")]

#plot, coloring each state by size
states.ranked<-
  us.states.contig@data[,rank(electoral.votes,
                              ties.method="first")]
cols<-colorRampPalette(c("red","blue"))(51)[states.ranked]

plot(us.states.contig,col=cols)

 Та же неискаженная карта штатов, но на этот раз каждый штат окрашен в красный, синий или фиолетовый цвет. Красный означает малое количество голосов коллегии выборщиков (например, Северная и Южная Дакота ярко-красные); синий цвет означает большое количество голосов коллегии выборщиков (  например, Техас и Калифорния ярко-синие); цвета на градиенте между ними означают средние голоса коллегии выборщиков

Это все хорошо — взглянув на эту карту, мы можем сказать, какие штаты имеют высокое и низкое представительство в коллегии выборщиков. Но что, если (как в нашей целевой карте) мы хотим представить другую переменную цветом состояния?

3. Добавьте результаты выборов 2012 г.

#scrape again
#2012 Election Results by State
election.wiki<-
  paste0("https://en.wikipedia.org/wiki/",
         "United_States_presidential_election,_2012")
         
results<-
  html(election.wiki) %>%
  html_node(xpath='//*[@id="mw-content-text"]/div[22]/table') %>%
  html_table()
#eliminate second header row, delete final row,
#  keep only the important columns
results.trim<-results[2:(nrow(results)-1),c(1,4,21)]
colnames(results.trim)<-c("name","pct","abbr")
results.dt<-setDT(results.trim)
#data idiosyncrasies, see Wiki page
results.dt<-results.dt[!grepl("–",abbr)|grepl("a",abbr)]
results.dt[grepl("–",abbr),abbr:=gsub("–.*","",abbr)]
results.dt[,"pct":=as.numeric(gsub("%","",pct))]

#merge
us.states.contig@data<-
  copy(us.states.contig@data
       )[results.dt,vote.pct:=i.pct,
         on=c(STUSPS="abbr")]
                              
pcts<-us.states.contig@data[,vote.pct]
cols<-c("red","blue")[(pcts>=50)+1L]
tx.col<-c("white","black")[(cols=="red")+1L]
plot(us.states.contig,col=cols)
text(coordinates(us.states.contig),
     us.states.contig@data[,paste0(STUSPS)],
     col=tx.col)

Этот последний график раскрывает суть проблемы. Первый представленный график намного лучше в том смысле, что по процентному соотношению красных и синих на карте мы можем определить, победили ли республиканцы или демократы; эта последняя карта вводит в заблуждение, потому что большинство республиканских штатов также являются самыми малонаселенными.

Есть ли способ создать искаженную версию этой карты, которая передает относительную важность каждого штата в коллегии выборщиков? Я не смог найти никакой помощи в Интернете, возможно, главным образом потому, что я не знаю, есть ли стандартное название для этого типа графика.

*Эта карта была найдена здесь; Я уже видел подобные искаженные по размеру карты, например. в The Economist. Похоже, что он основан на работе доктор Сэм Ван из Принстонского избирательного консорциума, продюсером которого выступил Дрю Талер.


person MichaelChirico    schedule 04.09.2015    source источник
comment
Искаженные карты обычно называют картограммами. У меня возникает соблазн пометить этот вопрос как дубликат этот вопрос. Есть пакет R, который делает это напрямую (не в CRAN, он указан в ответе, но выглядит ужасно устаревшим), но эта запись в блоге предполагает, что использование scape toad через R является более мощным.   -  person Gregor Thomas    schedule 05.09.2015
comment
@Грегор Я согласен, что это похоже на дубликат, но, как вы указали, возможно, это может быть обновление с предложенными вами функциями. спасибо за помощь со словарем. Я прочитаю их снова и опубликую в качестве ответа на этот или другой вопрос, используя жабу-ловушку.   -  person MichaelChirico    schedule 05.09.2015
comment
Да, это дубликат, но, учитывая возраст доступных ответов, есть много возможностей для улучшения,   -  person Gregor Thomas    schedule 06.09.2015
comment
@Gregor В записи в блоге, о которой вы упоминаете, действительно говорится, что ScapeToad является более мощным программным обеспечением, чем < href="http://www.omegahat.org/Rcartogram/" rel="nofollow noreferrer">пакет RCartogram. Мне было бы интересно узнать, в каком смысле ScapeToad мощнее. Алгоритм, используемый в ScapeToad, принадлежит Марку Ньюману и Майклу Гастнеру, а код во многом очень похож (исходный код C: здесь и описание алгоритма здесь.   -  person chkaiser    schedule 07.09.2015
comment
@chkaiser по сравнению со ScapeToad, я бы посчитал Rcartogram туманным / плохо документированным / предназначенным только для экспертов, другими словами, кривая обучения использованию Rcartogram довольно крутая. Ответ на другой вопрос, связанный здесь, упрощает это, и мы можем найти другие экземпляры пользователей, пытающихся понять, как использовать пакет.   -  person MichaelChirico    schedule 07.09.2015
comment
@MichealChirico Очень интересные и полезные моменты. Вероятно, нам следует улучшить документацию по Rcartogram. Существует также реализация командной строки ScapeToad от Луки Палли (форк мой репозиторий), который может помочь (хотя я еще не пробовал). Я рассматриваю возможность объединения его с моим репозиторием ScapeToad в ближайшее время или реализации аналогичной функциональности.   -  person chkaiser    schedule 08.09.2015


Ответы (1)


Следуя совету сопровождающего пакета @chkaiser, я искал и, наконец, нашел способ сделать это в R. Это сообщение в блоге очень помогло, а пакет getcartr просто фантастический.

Сначала получите пакеты Rcartogram и getcartr с GitHub:

remotes::install_github("omegahat/Rcartogram")
remotes::install_github('chrisbrunsdon/getcartr', subdir='getcartr')
library(Rcartogram)
library(getcartr)

Теперь просто подключи и пей:

us.states.contig.carto = quick.carto(
  us.states.contig,
  us.states.contig@data$electoral.votes
)
plot(us.states.contig.carto, col = cols)
text(
  coordinates(us.states.contig.carto),
  us.states.contig@data[ , paste0(STUSPS)],
  col = tx.col
)

И вот так у нас есть наша картограмма:

картограмма

person MichaelChirico    schedule 06.09.2015