21 июля 2013

Создание картограмм при помощи R. Часть 2



В предыдущем сообщении я показал, как при помощи пакетов maptools и sp можно создать картограммы на основе свободно доступных шейп-фалов. Как это часто случается, в R имеется несколько способов достижения одной и той же цели. Не являются исключением и картограммы. Это сообщение будет посвящено построению картограмм средствами ggplot2 - пожалуй, самого популярного графического пакета для R. Следует сразу оговориться, что синтаксис команд ggplot2 является своего рода мини-языком программирования. Изложение основ ggplot2 не является целью данной статьи - для этого существуют соответствующие руководства, из которых особое внимание стоит обратить на официальную документацию пакета, а также на книги Wickham (2009) и Chang (2013). В приведенных ниже примерах я буду давать лишь краткие пояснения к коду, необходимые для его понимания. Кроме того, предполагается, что вы уже знакомы с содержанием предыдущего сообщения.

Загрузим шейп-файл, необходимый для построения карты Беларуси и отображения ее административно-территориальных единиц на уровне районов:

load(url("http://gadm.org/data/rda/BLR_adm2.RData"))
Counties <- gadm
rm(gadm)

Как было отмечено ранее, объект Counties относится к объектам класса S4 и имеет сложную структуру. В то же время, единственный формат данных, который принимают функции пакета ggplot2, - это "таблица данных" (data frame). Соответственно, нам необходимо каким-то образом преобразовать объект Counties в таблицу данных. Сделать это позволяет функция fortify() из пакета ggplot2 (если этот пакет у вас еще не установлен, выполните команду install.packages("ggplot2")):

counties <- fortify(Counties, region = "NAME_2")
# при помощи аргумента region = "NAME_2" мы указываем
# переменную (NAME_2) в которой хранятся идентификаторы
# административных единиц - районов
 
str(counties)
'data.frame': 42659 obs. of  7 variables:
 $ long : num  29.1 29.1 29.1 29.1 29.1 ...
 $ lat  : num  52.9 52.9 52.9 52.9 52.8 ...
 $ order: int  1 2 3 4 5 6 7 8 9 10 ...
 $ hole : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ piece: Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
 $ group: Factor w/ 118 levels "Aktsyabar.1",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ id   : chr  "Aktsyabar" "Aktsyabar" "Aktsyabar" "Aktsyabar" ...

Теперь мы можем построить прототип нашей будущей картограммы при помощи следующей составной команды:

ggplot() + geom_map(data = counties, 
                    aes(map_id = id), 
                    map = counties, color = "gray70") +
  expand_limits(x = counties$long, y = counties$lat) +
  coord_map("polyconic")



Рассмотрим отдельные части приведенной команды подробнее:
  • ggplot(): создание статистических графиков средствами ggplot2 напоминает послойное создание изображений в программе Adobe Photoshop. При помощи функции ggplot() мы инициируем пустой слой графика, поверх которого далее будут добавляться другие слои, содержащие определенные графические элементы (в частности, изображение карты).
  • geom_map(): создает слой с картой, внешний вид которой задается при помощи соответствующих аргументов. Так, при помощи аргумента data мы указываем таблицу данных, в которой содержатся подлежащие отображению на карте данные. Поскольку на данном этапе никаких таких данных у нас нет, в качестве "заглушки" мы просто укажем таблицу counties. Аргумент aes() позволяет настроить "эстетические параметры" (англ. aesthetics) создаваемого слоя, и в частности - указать, какая переменная в таблице с данными содержит идентификаторы административно-территориальных единиц (районов). Аргумент map служит для указания таблицы, содержащей координаты соответствующих полигонов на карте (в нашем случае это counties - таблица, которую мы создали при помощи функции fortify() из объекта Counties).
  • expand_limits(): в отличие от других функций ggplot2, которые предназначены для создания новых слоев с графическими элементами, функция geom_map() "не умеет" самостоятельно определять оптимальные пределы значений x- и y-координат. Сделать это ей помогает функция expand_limits().
  • coord_map(): задает тип картографической проекции. В приведенном примере использован тип "polyconic" - поликоническая проекция. Доступны также многие другие типы, реализованные в пакете mapproj (подробнее см. справочный файл, доступный по команде ?mapproject).
Подобно тому, как это было сделано в предыдущем сообщении, мы создадим таблицу со случайным образом сгенерированными данными для каждого района Беларуси. Случайно сгенерированные данные будут использованы просто для иллюстрации принципа, однако при работе с "настоящими" данными последовательность шагов будет сходной. За основу таблицы с "фейковыми" данными возьмем содержимое слота data объекта Counties, после чего добавим к этой таблице столбец со случайными нормально распределенными значениями:

fake_data <- as.data.frame(Counties@data)
fake_data$Value <- rnorm(nrow(fake_data))

Теперь отобразим данные из столбца Value таблицы fake_data на картограмме:

ggplot() + geom_map(data = fake_data,
                    aes(map_id = NAME_2, fill = Value), 
                    map = counties) + 
  expand_limits(x = counties$long, y = counties$lat) +
  coord_map("polyconic")


Результатом приведенной выше команды будет картограмма с автоматически выбранной цветовой шкалой. Конечно, при желании мы можем изменить эту шкалу. Так, в рассматриваемом примере отображаемые на карте данные имеют среднее значение 0. Имеет смысл определенным образом выделить это значение на цветовой шкале, например, при помощи белого цвета. Для значений же, отклоняющихся от 0 в отрицательную и в положительную стороны, можно выбрать, например, оттенки синего и красного соответственно. Для создания подобных расходящихся (англ. diverging) цветовых шкал в пакете ggplot2 служит функция scale_fill_gradient2(), которая работает примерно следующим образом (обратите также внимание на аргумент colour = "gray" функции geom_map() - он добавлен для обводки границ районов серым цветом):

library(scales) # для функции muted (см. ниже)

ggplot() + geom_map(data = fake_data,
                    aes(map_id = NAME_2, fill = Value),
                    colour = "gray",
                    map = counties) + 
  expand_limits(x = counties$long, y = counties$lat) +
  scale_fill_gradient2(low = muted("blue"), 
                       midpoint = 0,
                       mid = "white",
                       high = muted("red"),
                       limits = c(min(fake_data$Value),
                                  max(fake_data$Value))) +
  coord_map("polyconic")


При необходимости мы можем выполнить тонкую настройку и других деталей внешнего вида графика. В частности, при помощи функции theme() ("тема", или "шаблон") можно отключить отображение серого фона, координатной сетки, а также осей и их подписей:


ggplot() + geom_map(data = fake_data,
                    aes(map_id = NAME_2, fill = Value),
                    colour = "gray",
                    map = counties) + 
  expand_limits(x = counties$long, y = counties$lat) +
  scale_fill_gradient2(low = muted("blue"), 
                       midpoint = 0,
                       mid = "white",
                       high = muted("red"),
                       limits = c(min(fake_data$Value),
                                  max(fake_data$Value))) +
  coord_map("polyconic") +
  theme(
    axis.line = element_blank(), 
    axis.text.x = element_blank(), 
    axis.text.y = element_blank(),
    axis.ticks = element_blank(), 
    axis.title.x = element_blank(), 
    axis.title.y = element_blank(),
    plot.background = element_blank(),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank()
  )




Комментариев нет :

Отправить комментарий