Круговая диаграмма в R c помощью ggplot: красные, зелёные, золотопогонные

В общем-то, круговые диаграммы — штука не особо удобная. Но есть такая вещь — традиция, поэтому в ряде случаев приходится всё-таки рисовать эти кружочки. Может, это корпоративный стиль такой — побольше круглого.

Рисование круговой диаграммы в ggplot представляет собой слегка нетривиальную задачу, ибо, как мы увидим дальше, она представляет собой… закрученную столбиковую диаграмму!

library(ggplot2)

Начнём однако, с данных, которые имеет смысл отображать подобным образом. Речь идёт о необходимости отразить на графике данные долей, в сумме дающих 100%. Нашим набором данных станут шесть населённых пунктов. Три из них заняты красными, два зелёными и один — золотопогонными.

vlast<-c("красные","красные", "красные", "зелёные", "зелёные", "золотопогонные")

А впрочем, нет, пусть лучше наши данные будут не вектором а переменной в наборе данных, это более частый случай:

data<-data.frame(vlast=vlast)

Нарисуем для начала простой столбик:

ggplot(data=data, aes(x="", fill=vlast)) + geom_bar(stat="bin")

Выглядит это так:



Информативно и понятно, но клиент заказывал круговые читаемые диаграммы с нарисованными там процентами. Продолжим… Добавим к нашему коду закручивание этого столбика в бублик:

+ coord_polar(theta=»y»)

Итак, нам осталось преобразовать первоначальные данные в проценты, убрать лишние подписи, красиво разместить их по графику и подобрать более удачные цвета.

Озаботившись первой проблемой, я сразу сталкиваюсь с тем, что как я ни бьюсь, описанное в куче руководств и ответов на вопросы + scale_y_continuous(labels = percent) — не работает. Может, это я делаю что-то не так, а может быть в ggplot опять изменился синтаксис. Вот в чём самая неприятная часть работы в R — положенные на полку заготовки могут в нужный момент подвести из-за изменений в синтаксисе. Но с процентами мы обязательно справимся. Тем более, что это не единственная проблема — надо ещё эти проценты красиво на графике разместить. Для этого мы преобразуем наши данные в таблицу частот:

1) Добавим в набор данных переменную-счётчик:
data$id
2) Подсчитаем, сколько в нашей переменной vlast значений (без пропушенных):
tbl Получается вот так:

vlast id
1 зелёные 2
2 золотопогонные 1
3 красные 3

3) Добавляем в таблицу новые интересные переменные:
tbl<-transform(tbl,freq=cumsum(id),perc=id/sum(id),pos=(cumsum(id)-0.5*id)/sum(id))

vlast id freq perc pos
1 зелёные 2 2 0.33 0.17
2 золотопогонные 1 3 0.17 0.42
3 красные 3 6 0.50 0.75

freq представляет собой кумулятивную частоту, perc — понятно, проценты, а pos — это будут координаты, куда мы будем рисовать наши проценты, так чтобы они попали в середину соответствующего куска пирога.

Теперь вместо stat=»bin» мы используем stat=»identity». Первый из этих методов отрисовывает высоту столбиков по количеству элементов в соответствующей группе, а второй — на основе числа, указанного в переменной y, в которую мы помещаем проценты:

ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(stat="identity") + coord_polar(theta="y")

Получается та же самая картинка, только по кругу нарисованы доли вместо частот. Теперь добавим width = 1, чтобы убрать дырочку из середины «бублика», чтобы он стал привычным Pie Chart (пирогом) и добавим метки-проценты:

ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(width = 1,stat="identity") + coord_polar(theta="y") + geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="white" ,size=7)

Размер стоит подстраивать под количество групп и итоговый размер всего графика.

Поправим цвета: + scale_fill_manual(vlast,values = c(«darkgreen»,»gold»,»red»)) (стоило бы подобрать цвета в шестнадцатиричной RRGGBB-кодировке, например «#FF3300″, а то эти какие-то уж очень ядовитые), а также уберём серенький фон с помощью указания на чёрно-белую тему theme_bw():

ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(width = 1,stat="identity") + coord_polar(theta="y") + geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="white" ,size=7)+ scale_fill_manual(vlast,values = c("darkgreen","gold","red")) + theme_bw()

Теперь уберём всё лишнее, путём приписывания element_blank():

ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(width = 1,stat="identity") + coord_polar(theta="y") + geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="white" ,size=7)+ scale_fill_manual(vlast,values = c("darkgreen","gold","red")) + theme_bw() +theme (panel.border = element_blank(),legend.title = element_blank(),axis.ticks = element_blank(),axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x = element_blank(),axis.line=element_blank(),panel.grid.major=element_blank())

Ну и последние штрихи: перенесём легенду вниз, чтобы эту картинку было удобнее использовать внутри текста и увеличим в ней размер шрифта, а также упорядочим с помощью указания breaks=c(«красные», «зелёные», «золотопогонные») . По каким-то мистическим причинам команда guide_legend не работает с такими графиками, так что приходится пользоваться теми опциями, которые есть в настройках темы:

ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(width = 1,stat="identity") + coord_polar(theta="y") + geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="white" ,size=7)+ scale_fill_manual(vlast,values = c("darkgreen","gold","red"), breaks=c("красные","зелёные","золотопогонные")) + theme_bw() +theme (panel.border = element_blank(),legend.title = element_blank(),axis.ticks = element_blank(),axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x = element_blank(),axis.line=element_blank(),panel.grid.major=element_blank(), legend.background = element_rect(fill="transparent"), legend.position=c(0.5,0), legend.direction="vertical", legend.text=element_text(size = 24))

Вот так вот. А теперь весь код целиком:

library(ggplot2)
library(grid)
vlast<-c("красные","красные", "красные", "зелёные", "зелёные", "золотопогонные") data<-data.frame(vlast=vlast) data$id<-c(1:nrow(data)) tbl<-aggregate(id ~ vlast, subset(data,!is.na(vlast)),length) tbl<-transform(tbl,freq=cumsum(id),perc=id/sum(id),pos=(cumsum(id)-0.5*id)/sum(id)) p<-ggplot(data=tbl, aes(x="", y=perc, fill = factor(vlast))) + geom_bar(width = 1,stat="identity") + coord_polar(theta="y") + geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="white" ,size=7)+ scale_fill_manual(vlast,values = c("darkgreen","gold","red"), breaks=c("красные","зелёные","золотопогонные")) + theme_bw() +theme (panel.border = element_blank(),legend.title = element_blank(),axis.ticks = element_blank(),axis.title.x = element_blank(), axis.title.y = element_blank(), axis.text.x = element_blank(),axis.line=element_blank(),panel.grid.major=element_blank(), legend.background = element_rect(fill="transparent"), legend.position=c(0.5,0), legend.direction="vertical", legend.text=element_text(size = 24)) library("Cairo") CairoPNG('pie.png',width=500,height=550) print(p) dev.off()

Можно вставить наш график в какую-нибудь презентацию:

About the Author: Владимир Волохонский
Владимир Волохонский - психолог, выпускник факультета психологии СПбГУ, с 2002 по 2011 преподавал там же дисциплины "Математические методы в психологии", "Дизайн психологического исследования", "Психометрия" и др. С 2011 года - индивидуальный предприниматель.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *