Показаны сообщения с ярлыком программирование. Показать все сообщения
Показаны сообщения с ярлыком программирование. Показать все сообщения

12 февр. 2013 г.

Построение страновых хороплет-карт (choropleth maps) с помощью пакета rworldmap в статистическом пакете R


Довольно часто социально-экономические данные удобно визуализировать с помощью карт. Стандартным является представление в форме так называемых choropleth maps (похоже, на русском они так и называются - хороплет-карты). Хороплет - это такая карта, на которой с помощью визуального оформления (обычно цвета, но может быть и к примеру, точками или линиями разной густоты/толщины) отображается интенсивность какого-либо показателя для географических регионов. Такие карты очень легко позволяют наглядно отобразить данные по большому количеству географических объектов.
Вот для примера такая карта - правда, наглядно? На ней изображена доля курильщиков среди мужчин по почти 150 странам. Создание такой карты в R заняло 8 строк кода, включая загрузку данных из Сети.
Smoking prevalence, males (% of adults)

Как создавать подобные карты?
Существует множество различных вариантов. В принципе, любая ГИС-программа типа MapInfo или ArcGIS умеет строить хороплет, но покупать эти дорогостоящие системы только для того, чтобы рисовать цветные карты, смысла не имеет. Можно рисовать карты хорорлет и в любимом Excel. Существует несколько "рецептов", как можно это делать.  Как правило, они требуют запуска VBA-макроса - для того, чтобы сопоставить исходный показатель с географическими регионами на карте. Еще одно условние - необходимо иметь исходную карту (линии) в графическом формате SVG. Это обычно не проблема, и другие гео-форматы можно тоже преобразовать в графический SVG, но это требует определенных манипуляций Вот один из предлагаемых рецептов, как построить карту хорорлет в Excel. Обратите внимание на то, сколько телодвижений надо сделать для того, чтобы нарисовать достаточно простую карту. Причем если даже процесс автоматизирован при смене данных (то есть, меняешь данные - карта перерисовывается), то при смене самой карты все ломается и требуется "доводка напильником" под новую карту.
 Наконец - обещанное. Конечно, хороплет-карты можно построить в статистическом пакете R. Возможности по работе с гео-данными в R, в том числе и графические, сопоставимы, а в некоторых случаях даже превосходят возможности полноценных ГИС-систем. И все это - в одном флаконе.

Сейчас я расскажу о простом и часто встречающемся случае - визуализация данных по странам как в случае нарисованного выше графика. Как обычно в R, для каждой специальной задачи уже есть созданный кем-то пакет. В нашем случае мы воспользуемся пакетом - rworldmap, созданный и поддерживамый Andy South. Основная его задача как раз в этом - построение хороплет-карт для страновых данных. Фактически этот пакет  - надстройка над другими, которые обеспечивают работу с гео-данными, но нас это не должно слишком волновать. Для нас пакет rworldmap сильно экономит время и строки для построения типовых страновых карт.

Краткая процедура построения выглядит следующим образом:

  1. Получение данных для отображения. В нашем случае мы используем данные из базы данных World Development Indicators (WDI), которую поддерживает Всемирный банк. В этой базе, как обещано, 331 показатель по 221 стране. Возьмем показатель "Smoking prevalence, males (% of adults)", который мне показался достаточно интересным. Загрузим его в R с помощью специального пакета, который носит название "WDI", как и следовало ожидать. Этот пакет позволяет обратиться напрямую к базе данных из R и получить данные сразу в необходимой разбивке "страна"-"год"-"показатель". Можно сразу загружать несколько показатель для диапазона лет для всех или некоторых стран. Очень удобно! В функции WDI() из одноименного пакета я рекомендую использовать параметр extra = TRUE для того, чтобы получаемые данные содержали код страны по ИСО (двух и трехзначный). 
  2. Сопоставление карты и данных. Для этого уже используется пакет rworldmap и его функция с говорящим названием joinCountryData2Map. Здесь все просто выбираем ключ, по которосу мы сопоставляем данные и карту. Это может быть название страны на английском языке, но лучше всего использовать коды стран по ISO (ISO2 или ISO3). Соответственно это параметр "joinCode". 
  3. Выбор показателя, который мы хотим отобразить на карте с помощью функции mapCountryData. Здесь все понятно  nameColumnToPlot соответственно название показателя, который хотим отобразить. Важными являются также параметры catMethod (определяет методы для категоризации данных, то есть деления их на группы одного цвета), а также colourPalette, который определяет цветовую палитру. Для палитры удобно использовать имеющиеся варианты из пакета RColorBrewer. Как выглядят сами палитры удобно смотреть на специальном сайте. 
  4. Дополнительно. Функция mapCountryData сразу же отображает карту, но если вы хотите внести некоторые изменения - в нашем случае немного поправить легенду с помощью addMapLegend. 
Вот код , который уже нарисует долю курильщиков-женщин по странам мира:

<!-- Styles for R syntax highlighter
require(WDI)
require(rworldmap)
require(RColorBrewer)

smoker <- WDI(country = "all", indicator = "SH.PRV.SMOK.FE", start = 2009, end = 2009, 
    extra = TRUE, cache = NULL)
# получить данные из WDI
fMap <- joinCountryData2Map(smoker, joinCode = "ISO3", nameJoinColumn = "iso3c", 
    nameCountryColumn = "country")
# cопоставить данные с картой по коду ISO3 (трехзначный код страны)
mapParams <- mapCountryData(fMap, nameColumnToPlot = "SH.PRV.SMOK.FE", catMethod = "quantiles", 
    missingCountryCol = gray(0.8), colourPalette = rev(brewer.pal(7, "RdYlBu")), 
    addLegend = FALSE, mapTitle = "")
# добавить легенду
do.call(addMapLegend, c(mapParams, legendLabels = "all", labelFontSize = 0.8, 
    legendWidth = 0.5, sigFigs = 0))

--> А вот и результат его выполнения:
Smoking prevalence, females (% of adults)
По картам можно сразу же сделать несколько наблюдений. Среди мужчин больше всего курят Россия, Китай, Восточная Европа и Малайзия с Индонезией. Среди женщин все по другому - здесь в лидерах жительницы стран Западной Европы (Австрия на первом месте), Чили и  Папуа-Новая Гвинея.

5 мая 2012 г.

Получение подробных данных по бюджетам субъектов РФ

Большую часть экономики составляет бюджетный сектор. В прошлом году расходы консолидированного бюджета РФ составили чуть больше 20 трлн рублей (около 37% ВВП), из них на федеральный бюджет пришлось почти 11 трлн рублей, остальное - внебюджетные фонды, бюджеты субъектов РФ и муниципальные бюджеты.
Не так давно встала задача с получением и анализом довольно подробных данных по бюджетам отдельных субъектов РФ. Основным источником информации является отчетность Федерального Казначейства, который ежемесячно предоставляет данные об исполнении бюджетов. В случае федерального бюджета за каждый месяц - это стандартный набор файлов Excel.
Для региональных бюджетов - все гораздо сложнее. Казначейство выкладывает огромный архив (данные за каждый месяц в архиве занимают более 10 мегабайт) html-файлов. Структура данных простая: "регион-бюджетная форма отчетности" - отдельный файл.
Министерство финансов проводит некоторую аналитическую работу и предоставляет те же данные в более удобоваримом виде. Однако в случае данных Минфина возникает две проблемы:

  1. Набор показателей включает в себя базовые вещи вроде общих расходов и доходов регионального бюджета, но набор специфических показателей достаточно скуден. 
  2. Данные начинаются с февраля 2011 года, хотя Казначейство дает информацию аж с 2000 года. 

Что делать, если нужны подробные данные и длинная история? Как обычно, если цифр немного, то проще всего собрать цифры ручками. В противном случае, приходится "изобретать велосипед" и пытаться автоматизировать процесс, так как источники информации мало заботятся о нуждах простых аналитиков.
Когда возникла подобная необходимость, я написал набор скриптов на Python, которые обрабатывали предварительно сохраненные на локальном диске папки с исходными файлами. На каждый год я создавал отдельный скрипт для того, чтобы можно было посмотреть исходные данные. К  сожалению, из-за того, что коды бюджетной классификации регулярно меняются, как и формат предоставления данных. Поэтому скрипт, написанный для данных 2010 года, потребует, незначительной "подкрутки" для того, чтобы работать на данных 2006 года.
Для обработки html файлов я использовал отличную библиотеку Beautiful Soup. Парсинг файлов занимает относительно много времени (около 30-40 секунд для отдельного файла), поэтому скрипт работает довольно долго (около 10-15 минут на моем компьютере). Но так как он работает сам по себе, в это время можно заниматься другими полезными вещами.
  
Исходные коды, если кому-то пригодятся (так как я не программист, то код, видимо, не самый оптимальный): 

26 апр. 2012 г.

Макрос Excel для преобразования таблиц в вид, пригодный для баз данных

Одной из неприятных проблем при обработке количественных данных является преобразование их в нужной формат и нужный вид. Как правило, данные содержатся не в том виде, в котором удобно их анализировать. Для небольшого объема это можно делать вручную. Причем часто лучше так и поступить - разработка какого-то специального инструмента автоматизации для данных, которые могут легко измениться или их не так много, возможно, не имеет смысл. И проще все "перебить руками".
Но если речь идет о сотнях или тысячах показателей или подобная задача встает с определенной регулярностью, стоит подумать над автоматизацией процесса. 
Приведу простой пример. Исходный файл в формате Excel выглядит подобным образом: 


                                             
Данные (это цены на различные корпоративные облигации, скачанные из Bloomberg) сгруппированы на одном листе в группы по три строки:
  1. идентификатор облигации;
  2. дата;
  3. цена. 
Для каждой бумаги (то есть  каждой группы из трех столбцов), ее длина отличается произвольным образом. Это происходит потому, что разные бумаги начали торговаться в разные периоды времени, для некоторых периодов есть пропуски и так далее.  
Для того, чтобы использовать их в собственной базе данных для дальнейшей обработки, необходимо свести их в "нормальный" вид - в одну таблицу по три столбца, в которой бумаги с соответствующими им идентификаторами идут "сверху вниз". 
В принципе, это достаточно часто встречающая задача, когда из обычного экселелевского вида таблицы нужно преобразовать данные для анализа в формате сводных таблиц или обработки в базе данных. В данном случае ее можно довольно легко решить и средствами СУБД, но мы воспользовались средствами Excel, так как для наших целей мы используем загрузку данных из Bloomberg в Excel, а не сразу в СУБД. 
Для того, чтобы решить эту задачу я написал небольшой макрос, который состоит из процедуры и функции. Процедура "проходит" по всему листу с данными, до тех пор пока находит что-то в первой строчке (в нашем случае это формула в каждом третьем столбце) и копирует их на новый лист. Функция же находит последнюю ненулевую строку в данном столбце и возвращает ее номер. 
Исходные коды, если кому-то пригодятся для своих целей: