Pavel Polishchuk, 2014
Графические возможности R с пакетом ggplot2
ggplot2
- Wickham, Hadley. ggplot2: Elegant Graphics for Data Analysis. Dordrecht, Heibelberg, London, New York: Springer, 2009.ggplot2
Пакет ggplot2
предназначен для построения двумерных графиков и диаграмм.
График в рамках пакета ggplot2
представляется как конструктор, состоящий из отдельных частей, которые можно соединять произвольным образом, чтобы достичь желаемого эффекта.
Основные кирпичики графического конструктора (первые три их них являются обязательными составляющими):
data
- data.frame
, содержащий данные для представления.aes()
- задает связь между данными и их представлением, определяет какие переменные отображаются на осях, какие переменные отвечают за цвет и форму данных, представленных на графике.geom_
- группа функций, отвечающих за то что, вы непосредственно видите на графике (точки, гистограммы, линии, текст и т.п.).scale_
- группа функций, соотносящих реальные данные с их графическим представлением. Это может быть цвет, форма, размер, диапазон осей координат и т.п.stat_
- группа функций, добавляющих на график различные статистические показатели, например, такие как, среднее значение по группе, линейная или иная аппроксимация данных и т.п.coord_
- группа функций, которая задает систему координат для представления данных на плоскости. Это могут быть обычные картезианские координаты, полярные координаты, или географические координаты для представления соответствующих данных.facet_
- группа функций, которые позволяют группировать графики по заданному параметру и представлять результаты в виде набора графиков (сетки из графиков).theme
- группа функций, позволяющих менять оформление графика, например размер и цвет шрифта координатных осей и делений на них, фон графика и всего рисунка и т.п.Возьмем за основу значения растворимости предсказанные ранее различными моделями. Эти данные можно загрузить с сайта, а можно использовать те, которые были получены в ходе самостоятельного моделирования.
cv <- read.table("data/cv_pred.txt", sep="\t", header=TRUE, as.is=TRUE)
test <- read.table("data/test_pred.txt", sep="\t", header=TRUE, as.is=TRUE)
head(cv)
m.gbm m.knn m.pls m.rf m.svm mean
sol_10001 -2.799118 -3.626667 -2.148206 -3.000497 -2.677521 -2.850402
sol_10002 -2.683472 -3.553333 -2.214603 -2.639931 -2.540740 -2.726416
sol_10003 -2.589948 -3.603333 -2.378869 -3.280679 -3.100913 -2.990748
sol_10004 -2.639194 -3.853333 -2.297653 -3.249204 -3.106995 -3.029276
sol_10005 -3.001957 -2.823333 -1.795756 -3.036543 -2.766391 -2.684796
sol_10006 -3.231845 -3.556667 -2.535705 -3.353757 -3.070914 -3.149778
nnls
sol_10001 -2.823609
sol_10002 -2.657990
sol_10003 -2.973854
sol_10004 -2.984015
sol_10005 -2.922233
sol_10006 -3.233097
head(test)
m.gbm m.knn m.pls m.rf m.svm mean
sol_10801 -1.1778582 -0.440000 -0.3168113 -0.8795913 -0.6089708 -0.6846463
sol_10802 -1.0579281 -0.440000 -0.2862568 -1.0169123 -1.0142728 -0.7630740
sol_10803 -0.7143699 -0.440000 -0.2963245 -1.1513807 -1.7784464 -0.8761043
sol_10804 -0.8748695 -0.440000 -0.0164618 -1.1532090 -2.2388806 -0.9446842
sol_10805 -0.9348645 -1.346667 -1.4939263 -1.1176407 -0.8709753 -1.1528147
sol_10806 -1.7129724 -1.473333 -1.3859660 -1.2913827 -1.3519756 -1.4431260
nnls
sol_10801 -0.8803242
sol_10802 -1.0139525
sol_10803 -1.1994194
sol_10804 -1.4198597
sol_10805 -1.0024755
sol_10806 -1.5129118
Округлим результаты для лучшего восприятия данных
cv <- round(cv, 2)
test <- round(test, 2)
head(cv)
m.gbm m.knn m.pls m.rf m.svm mean nnls
sol_10001 -2.80 -3.63 -2.15 -3.00 -2.68 -2.85 -2.82
sol_10002 -2.68 -3.55 -2.21 -2.64 -2.54 -2.73 -2.66
sol_10003 -2.59 -3.60 -2.38 -3.28 -3.10 -2.99 -2.97
sol_10004 -2.64 -3.85 -2.30 -3.25 -3.11 -3.03 -2.98
sol_10005 -3.00 -2.82 -1.80 -3.04 -2.77 -2.68 -2.92
sol_10006 -3.23 -3.56 -2.54 -3.35 -3.07 -3.15 -3.23
head(test)
m.gbm m.knn m.pls m.rf m.svm mean nnls
sol_10801 -1.18 -0.44 -0.32 -0.88 -0.61 -0.68 -0.88
sol_10802 -1.06 -0.44 -0.29 -1.02 -1.01 -0.76 -1.01
sol_10803 -0.71 -0.44 -0.30 -1.15 -1.78 -0.88 -1.20
sol_10804 -0.87 -0.44 -0.02 -1.15 -2.24 -0.94 -1.42
sol_10805 -0.93 -1.35 -1.49 -1.12 -0.87 -1.15 -1.00
sol_10806 -1.71 -1.47 -1.39 -1.29 -1.35 -1.44 -1.51
Добавим к этим данным наблюдаемые значения растворимости
y <- local.load("data/sol_y1.RData")
y.test <- local.load("data/sol_y2.RData")
cv$obs <- y
test$obs <- y.test
И добавим колонку в которой укажем, какому набору принадлежат данные кросс-валидации или тестовой выборке.
cv$set <- "cv"
test$set <- "test"
head(cv)
m.gbm m.knn m.pls m.rf m.svm mean nnls obs set
sol_10001 -2.80 -3.63 -2.15 -3.00 -2.68 -2.85 -2.82 -3.18 cv
sol_10002 -2.68 -3.55 -2.21 -2.64 -2.54 -2.73 -2.66 -2.64 cv
sol_10003 -2.59 -3.60 -2.38 -3.28 -3.10 -2.99 -2.97 -3.84 cv
sol_10004 -2.64 -3.85 -2.30 -3.25 -3.11 -3.03 -2.98 -3.74 cv
sol_10005 -3.00 -2.82 -1.80 -3.04 -2.77 -2.68 -2.92 -3.55 cv
sol_10006 -3.23 -3.56 -2.54 -3.35 -3.07 -3.15 -3.23 -3.10 cv
head(test)
m.gbm m.knn m.pls m.rf m.svm mean nnls obs set
sol_10801 -1.18 -0.44 -0.32 -0.88 -0.61 -0.68 -0.88 -1.11 test
sol_10802 -1.06 -0.44 -0.29 -1.02 -1.01 -0.76 -1.01 -0.91 test
sol_10803 -0.71 -0.44 -0.30 -1.15 -1.78 -0.88 -1.20 -1.76 test
sol_10804 -0.87 -0.44 -0.02 -1.15 -2.24 -0.94 -1.42 -2.36 test
sol_10805 -0.93 -1.35 -1.49 -1.12 -0.87 -1.15 -1.00 -0.86 test
sol_10806 -1.71 -1.47 -1.39 -1.29 -1.35 -1.44 -1.51 -1.16 test
Объединим эти два набора данных в один. Поскольку порядок следования данных в колонках совпадает можно применить функцию объединения по строкам rbind
df <- rbind(cv, test)
Все эти манипуляции конечно не обязательны при работе с реальными данными, а служат лишь для того, чтобы продемонстрировать способы работы с данными и подготовки их к дальнейшей отрисовке.
Нарисуем графики распределения предсказанных и наблюдаемых значений для каждой из моделей. По мере продвижения к цели будут продемонстрированы некоторые возможности ggplot2
.
Начнем с самого простого. Нарисуем точечную диаграмму распределения наблюдаемых и предсказанных значений для модели gbm
. Т.е. используем три обязательных компонента data
, aes
и geom_
.
require(ggplot2)
# single model plot
g1 <- ggplot(df, aes(x=obs, y=m.gbm)) + geom_point()
g1
В ggplot2
есть альтернативный более простой вариант для создания диаграмм - функция qplot
, которая во многом похожа на обычную функцию plot
. Она не обладает большим разнообразием возможностей и подходит для быстрого построения не очень сложных графиков.
# shorter version
g1.1 <- qplot(x=obs, y=m.gbm, data=df, geom="point")
g1.1
# even shorter one
g1.2 <- qplot(x=df$obs, y=df$m.gbm, geom="point")
g1.2
У нас на графике совместно представлены данные для кросс-валидации и внешнего теста, разделим их по цвету точек.
# add color to distinguish cv and test
g2 <- ggplot(df, aes(x=obs, y=m.gbm, color=set)) +
geom_point()
g2
Добавим дифференциацию точек по форме, задав соответствующее условие.
# add color and shape to distinguish cv and test
g3 <- ggplot(df, aes(x=obs, y=m.gbm, color=set, shape=set)) +
geom_point()
g3
Если мы хотим увеличить размер точек (задать фиксированный размер), то для этого используются параметры функции geom_point
.
# change point size
g4 <- ggplot(df, aes(x=obs, y=m.gbm, color=set, shape=set)) +
geom_point(size=3)
g4
Чтобы было лучше видно перекрывающиеся точки, их можно сделать полупрозрачными.
# add transparency to view overlapping points
g5 <- ggplot(df, aes(x=obs, y=m.gbm, color=set, shape=set)) +
geom_point(size=3, alpha=0.5)
g5
Добавим на наш график диагональную линию соответствующую идеальному случаю прогноза.
# add a diagonal line of perfect prediction
# since aes in main function relates to all data we set shape and color inside the geom_point function
g6 <- ggplot(df, aes(x=obs, y=m.gbm, color=set, shape=set)) +
geom_point(size=3, alpha=0.5) +
geom_abline(intercept=0, slope=1)
g6
Отметим важность очередности следоваания вызова функция для рисования отдельных слоев. Эта очередность определяет последовательность отображения данных на графике.
# order of calls is important it determines to order of layers on the plot
g7 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5)
g7
stat_
Добавим на график элемент stat_
- в нашем случае это будет прямая представляющая собой линейную зависимость предсказанных и наблюдаемых значений. Обратите внимание, что мы к ранее созданному объекту класса ggplot
может добавлять новые элементы (режим конструктора!).
# add stat to modify previously created plot - it's really like a LEGO!
g8 <- g7 + stat_smooth(method="lm")
g8
Чтобы аппроксимация строилась для каждой из двух групп точек отдельно укажем это явно в вызываемой функции.
# make stat for each group of point separately
g9 <- g7 + stat_smooth(method="lm", aes(group=set))
g9
В дальнейшем мы будем использовать полный вызов функции.
Удалим из аппроксимирующей зависимости отображение диапазона ошибки аппроксимации, отобразим линии на всем диапазоне графика и представим их цветом соответствующем набору данных.
# to be clear further we will use full plot call
# remove SE and extend lines to full range and set a color for each line
g10 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE)
g10
scale_
Применим какую-либо функцию из семейства функций scale_
, например, изменим цветовое представление графика.
# use scale for colors (it is possible to scale other aestetics)
g11 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_grey()
g11
Выглядит не очень удачно. Зададим цвета самостоятельно.
# looks bad, lets scale manually to set colors
g12 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_manual(values=c("red", "blue"))
g12
Цвет можно определять также и соответствующим RGB кодом цвета.
# you can use RGB codes for colors
g12.1 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_manual(values=c("#FF22FF", "#2255FF"))
g12.1
Соответствующими функциями scale_
можно инвертировать оси координат.
# another usage of scale applied for axis
g12.2 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_x_reverse()
g12.2
g12.3 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_x_reverse() +
scale_y_reverse()
g12.3
Координатные оси можно поменять местами при необходимости
# flip coords to exchange axis
g12.4 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_manual(values=c("red", "blue")) +
coord_flip()
g12.4
theme
Управлять отрисовкой отдельных элементов можно использую функции семейства theme_
.
# use theme to control graphic output
# there are several predifined themes, but you may create your own
# to descrease amount of code to copy-paste return to the LEGO mode
g13 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_manual(values=c("red", "blue"))
g13
g13.1 <- g13 + theme_bw()
g13.1
g13.2 <- g13 + theme_classic()
g13.2
g13.3 <- g13 + theme_minimal()
g13.3
В пакете ggplot2
предусмотрен ограниченный набор функций theme_
. Чтобы самостоятельно управлять отрисовкой отдельных элементов графика следует воспользоваться функцией theme
.
Например, изменим цвет, положение, размер шрифта и угол наклона подписей по оси Х.
# change x labels
g13.4 <- g13 +
theme(axis.text.x = element_text(color="red", size=15, angle=45, hjust=1))
g13.4
Изменим цвет рамки и заливки для области построения диаграммы.
# change plot area background
g13.5 <- g13 +
theme(axis.text.x = element_text(color="red", size=15, angle=45, hjust=1),
panel.background = element_rect(color="pink", fill="lightyellow"))
g13.5
Удалим с диаграммы все линии сетки (основные и промежуточные)
# remove all grid lines
g13.6 <- g13 +
theme(axis.text.x = element_text(color="red", size=15, angle=45, hjust=1),
panel.background = element_rect(color="pink", fill="lightyellow"),
panel.grid = element_blank())
g13.6
facet_
Разделим диаграммы для двух наборов данных.
# facet
g14 <- ggplot(df, aes(x=obs, y=m.gbm)) +
geom_abline(intercept=0, slope=1) +
geom_point(aes(color=set, shape=set), size=3, alpha=0.5) +
stat_smooth(method="lm", aes(group=set, color=set), fullrange=TRUE, se=FALSE) +
scale_color_manual(values=c("red", "blue")) +
facet_wrap(~set)
g14
Используем наш набор данных для того, чтобы посмотреть распределение свойства для обучающей и тестовой выборок. Ранее мы использовали с этой целью функцию hist
.
# look at distribution of training and test sets data
g15 <- ggplot(df, aes(x=obs)) +
geom_histogram()
g15
stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.
Зададим ширину каждого столбца в гистограмме
g15.1 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1)
g15.1
Раскрасим столбцы в соответствии с выборками
g15.2 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1, aes(fill=set))
g15.2
Добавим для большей привлекательности белые линии в качестве границ
g15.3 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1, aes(fill=set), color="white")
g15.3
Разделим гистограмму на две в соответствии с выборками.
g15.4 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1, aes(fill=set), color="white") +
facet_wrap(~set)
g15.4
Чтобы расположить их друг под другом зададим параметр ncol
g15.5 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1, aes(fill=set), color="white") +
facet_wrap(~set, ncol=1)
g15.5
Можно изменить диапазон значений по каждой или по обеим осям такой диаграммы. Например, зададим, чтобы диаграмммы по оси Y имели независмые шкалы.
g15.6 <- ggplot(df, aes(x=obs)) +
geom_histogram(binwidth=1, aes(fill=set), color="white") +
facet_wrap(~set, ncol=1, scales="free_y")
g15.6
Вместо гистограмм можно представить распределение данных в виде диаграммы плотности распределения.
g15.7 <- ggplot(df, aes(x=obs)) +
geom_density(aes(fill=set), color="white") +
facet_wrap(~set, ncol=1)
g15.7
Отобразим в виде точечных диаграмм наблюдаемые и прогнозируемые значения для каждой модели и для каждого набора данных одновременно.
Но прежде надо преобразовать соответствующим образом имеющиеся данные, чтобы их можно было использовать для создания диаграммы.
# let's plot predictions of all models simultaneously
# but first we need to prepare the data
df1 <- reshape::melt.data.frame(df, id.vars=c("set","obs"))
head(df1)
set obs variable value
1 cv -3.18 m.gbm -2.80
2 cv -2.64 m.gbm -2.68
3 cv -3.84 m.gbm -2.59
4 cv -3.74 m.gbm -2.64
5 cv -3.55 m.gbm -3.00
6 cv -3.10 m.gbm -3.23
dim(df1)
[1] 7231 4
colnames(df1)[3:4] <- c("model", "pred")
head(df1)
set obs model pred
1 cv -3.18 m.gbm -2.80
2 cv -2.64 m.gbm -2.68
3 cv -3.84 m.gbm -2.59
4 cv -3.74 m.gbm -2.64
5 cv -3.55 m.gbm -3.00
6 cv -3.10 m.gbm -3.23
Теперь можно рисовать
# let's draw
g16 <- ggplot(df1, aes(x=obs, y=pred)) +
geom_point(aes(color=set)) +
facet_wrap(~ model)
g16
g16.1 <- g16 + theme_classic()
g16.1
Другой пример - покажем в виде столбчатой диаграммы ошибки моделей (MSE) для кросс-валидации и внешнего теста.
Предварительно вычислим ошибку для каждой точки и построим диаграмму с одновременным подсчетом MSE модели.
# calc prediction error and visualize it
df1$mse <- (df1$obs - df1$pred) ^ 2
g17 <- ggplot(df1, aes(x=model, y=mse)) +
geom_bar(stat="summary", fun.y="mean", aes(fill=set), position="dodge")
g17
g17 + theme_bw()
g17 + theme_classic()
Для этого используется функция ggsave
, которая имеет много параметров, позволяющих управлять результатом.
ggsave("data/plot.jpg", plot=g17 + theme_classic(), width=20, height=15, units="cm", dpi=600)
Функция сохранения поддерживает различные форматы файлов (png, tiff и т.д.).