В среде R представлены 3 разные системы построения
графиков. Изначально в эту систему была заложена так называемая базовая
графика, base graphics, позже появилась система lattice, которая
позволяет комбинировать несколько графиков в виде такого комбинированного
рисунка, и позже появилась система ggplot2, которую будем рассматривать в этой статье.
Система ggplot2 получила своё название от трёх слов - Grammar, Graphics, Plot..
Он построен на концепции грамматики графика, представленная Уилкинсоном в 1999 году, и эта грамматика графики была реализована в R пакет Хэдли Уикхем в 2005 году. График в рамках пакета
Для демонстрации приемов работы с графикой загрузим датафрейм с дневными продажи футболок в розничном магазине одежды
df <- read_excel("ShopSaleTS.xlsx")
head(df)
str(df)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1300 obs. of 7 variables:
$ Date : POSIXct, format: "2019-06-01" "2019-06-01" "2019-06-01" ...
$ Gender : chr "Female" "Male" "Female" "Male" ...
$ Category: chr "T-shirt" "T-shirt" "T-shirt" "T-shirt" ...
$ ProdCode: chr "TSSQ55265" "TSSQ54736" "TSSQ60427" "TSSQ45158" ...
$ Size : chr "S" "M" "L" "S" ...
$ Sale : num 1 1 1 1 1 1 1 1 1 1 ...
$ Price : num 999 849 3999 1899 1899 ...
Сделаем некоторые преобразования переменных, переведем переменные пол и размер в факторные переменные
df<- mutate(df,Date=as.Date(Date),
Gender=factor(Gender,order = TRUE, levels=c('Female','Male')),
Size=factor(Size,order = TRUE,
levels=c('XS','S','M','L','XL','XXL','3XL','4XL','5XL')))
str(df)
Одномерная визуализация числовой переменной
Гистограмма
При построении гистограммы отобрал самые необходимые с моей точки зрения настройки
binsize <- diff(range(df$Price))/10 #ширина шага
ggplot(df, aes(x = Price)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, fill = "white", colour = "black",boundary=50)+
coord_cartesian(ylim = c(0,350))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) #Заголовок по центру
Разделим гистограмму по полу на две гистограммы
ggplot(df, aes(x = Price)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, fill = "white", colour = "black",boundary=50)+
coord_cartesian(ylim = c(0,350))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) + #Заголовок по центру
facet_grid(Gender ~ .) #Делим на две гистограммы по полу
На одной гистограмме разделим данные по полу по цвету и добавим на гистограмму средние цены продаж по полу
mean_price <- df %>%
group_by(Gender) %>%
summarise(avg_price = mean(Price))
ggplot(df, aes(x = Price, fill = Gender)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, colour = "black",
boundary=50,position = "identity", alpha = 0.4)+
coord_cartesian(ylim = c(0,200))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) + #Заголовок по центру
geom_vline(
data = mean_price,
aes(xintercept = avg_price, colour = Gender),
linetype = "dashed",
size = 1
) #Добавляем средние цены продажи по полу
Boxplot
Этот тип графика также вывожу с основными настройками и с обозначение средних значений цен по мужским и женским футболкам
ggplot(df, aes(x=Gender,y = Price,fill=Gender)) +
geom_boxplot(outlier.color = "red", outlier.size = 5) + #Выделяем выбросы
geom_hline(data = mean_price,
aes(yintercept = avg_price, colour = Gender),
linetype = "dashed",
size = 1) + #Добавляем средние значения цен по полу
scale_fill_manual(values = c("#FFCCCC","#99CCFF"))+ #Задаем свой набор цветов заливки
scale_color_manual(values = c("red", "black")) #Задаем свой набор цветов линий средних значений
Можно разделить по полу и размерам
ggplot(df, aes(x=interaction(Gender,Size),y = Price,fill=Gender)) +
geom_boxplot()+
theme(axis.text.x = element_text(angle=45,size=10))+ #Задаем размер и угол наклона обозначений по оси x
scale_fill_manual(values = c("#FFCCCC","#99CCFF"))
Вывод графика в форме Violin хорош тем, что он показывает плотность вероятности данных при различных значениях. Это дает представление о форме распределения данных
ggplot(data = df %>% filter(Gender =='Female'), mapping = aes(x= Size)) +
geom_bar() +
geom_text(aes(label = ..count..), stat = "count", vjust = 1.5,colour = "white")
Выведем диаграмму в процентах
ggplot(data = df %>% filter(Gender =='Female'), mapping = aes(x= Size)) +
geom_bar(aes(y=..count../sum(..count..))) +
scale_y_continuous(labels = scales::percent_format())
Выведем распределение по полу
ggplot(data = df , mapping = aes(x= Gender,fill=Gender)) +
geom_bar(position="dodge") +
scale_fill_manual(values =c("#FF3399","#3399FF"))
Распределение по полу и по размерам
ggplot(data = df , mapping = aes(x= Size,fill=Gender)) +
geom_bar(position="dodge") +
scale_fill_manual(values =c("#FF3399","#3399FF"))
ggplot(df, aes(x = Visit, y = Rent, colour = City)) +
geom_point()
df1 <- read_excel("ShopSaleTS.xlsx")
df1<- mutate(df1,Date=as.Date(Date),
Gender=factor(Gender,order = TRUE, levels=c('Female','Male')),
Wday = factor(wday(Date,week_start =1)))
head(df1)
cross_tab <- xtabs(~Gender+Wday, data=df1)
cross_tab
head(df1)
Система ggplot2 получила своё название от трёх слов - Grammar, Graphics, Plot..
Он построен на концепции грамматики графика, представленная Уилкинсоном в 1999 году, и эта грамматика графики была реализована в R пакет Хэдли Уикхем в 2005 году. График в рамках пакета
ggplot2
представляется как конструктор, состоящий из отдельных частей, которые можно соединять произвольным образом, чтобы достичь желаемого эффекта.
Основные кирпичики графического конструктора (первые три их них являются обязательными составляющими):
data
-data.frame
, содержащий данные для представления.aes()
- задает связь между данными и их представлением, определяет какие переменные отображаются на осях, какие переменные отвечают за цвет и форму данных, представленных на графике.geom_
- группа функций, отвечающих за то что, вы непосредственно видите на графике (точки, гистограммы, линии, текст и т.п.).scale_
- группа функций, соотносящих реальные данные с их графическим представлением. Это может быть цвет, форма, размер, диапазон осей координат и т.п.stat_
- группа функций, добавляющих на график различные статистические показатели, например, такие как, среднее значение по группе, линейная или иная аппроксимация данных и т.п.coord_
- группа функций, которая задает систему координат для представления данных на плоскости. Это могут быть обычные картезианские координаты, полярные координаты, или географические координаты для представления соответствующих данных.facet_
- группа функций, которые позволяют группировать графики по заданному параметру и представлять результаты в виде набора графиков (сетки из графиков).theme
- группа функций, позволяющих менять оформление графика, например размер и цвет шрифта координатных осей и делений на них, фон графика и всего рисунка и т.п.
Для демонстрации приемов работы с графикой загрузим датафрейм с дневными продажи футболок в розничном магазине одежды
df <- read_excel("ShopSaleTS.xlsx")
head(df)
# A tibble: 6 x 7
Date Gender Category ProdCode Size Sale Price
<dttm> < chr> <chr> <chr> < chr> <dbl> <dbl>
1 2019-06-01 00:00:00 Female T-shirt TSSQ55265 S 1 999
2 2019-06-01 00:00:00 Male T-shirt TSSQ54736 M 1 849
3 2019-06-01 00:00:00 Female T-shirt TSSQ60427 L 1 3999
4 2019-06-01 00:00:00 Male T-shirt TSSQ45158 S 1 1899
5 2019-06-01 00:00:00 Female T-shirt TSSQ45162 XS 1 1899
6 2019-06-01 00:00:00 Female T-shirt TSSQ51697 XL 1 999
str(df)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1300 obs. of 7 variables:
$ Date : POSIXct, format: "2019-06-01" "2019-06-01" "2019-06-01" ...
$ Gender : chr "Female" "Male" "Female" "Male" ...
$ Category: chr "T-shirt" "T-shirt" "T-shirt" "T-shirt" ...
$ ProdCode: chr "TSSQ55265" "TSSQ54736" "TSSQ60427" "TSSQ45158" ...
$ Size : chr "S" "M" "L" "S" ...
$ Sale : num 1 1 1 1 1 1 1 1 1 1 ...
$ Price : num 999 849 3999 1899 1899 ...
Сделаем некоторые преобразования переменных, переведем переменные пол и размер в факторные переменные
df<- mutate(df,Date=as.Date(Date),
Gender=factor(Gender,order = TRUE, levels=c('Female','Male')),
Size=factor(Size,order = TRUE,
levels=c('XS','S','M','L','XL','XXL','3XL','4XL','5XL')))
str(df)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1300 obs. of 7 variables:
$ Date : Date, format: "2019-06-01" "2019-06-01" "2019-06-01" ...
$ Gender : Ord.factor w/ 2 levels "Female"<"Male": 1 2 1 2 1 1 2 2 2 2 ...
$ Category: chr "T-shirt" "T-shirt" "T-shirt" "T-shirt" ...
$ ProdCode: chr "TSSQ55265" "TSSQ54736" "TSSQ60427" "TSSQ45158" ...
$ Size : Ord.factor w/ 9 levels "XS"<"S"<"M"<"L"<..: 2 3 4 2 1 5 6 6 3 3 ...
$ Sale : num 1 1 1 1 1 1 1 1 1 1 ...
$ Price : num 999 849 3999 1899 1899 ...
Одномерная визуализация числовой переменной
Гистограмма
При построении гистограммы отобрал самые необходимые с моей точки зрения настройки
binsize <- diff(range(df$Price))/10 #ширина шага
ggplot(df, aes(x = Price)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, fill = "white", colour = "black",boundary=50)+
coord_cartesian(ylim = c(0,350))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) #Заголовок по центру
Разделим гистограмму по полу на две гистограммы
ggplot(df, aes(x = Price)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, fill = "white", colour = "black",boundary=50)+
coord_cartesian(ylim = c(0,350))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) + #Заголовок по центру
facet_grid(Gender ~ .) #Делим на две гистограммы по полу
На одной гистограмме разделим данные по полу по цвету и добавим на гистограмму средние цены продаж по полу
mean_price <- df %>%
group_by(Gender) %>%
summarise(avg_price = mean(Price))
ggplot(df, aes(x = Price, fill = Gender)) +
#fill - цвет заливки, colour - цвет границы, boundary - выравнивание границ классов
geom_histogram(binwidth = binsize, colour = "black",
boundary=50,position = "identity", alpha = 0.4)+
coord_cartesian(ylim = c(0,200))+ #Диапазон по оси y
xlab("Price T-Shirt") + #Название оси x
ylab("Sales")+ #Название оси y
ggtitle("T-shirt sales in price ranges","June 2019") + #Заголовок из двух строк
theme(plot.title = element_text(hjust = 0.5)) + #Заголовок по центру
geom_vline(
data = mean_price,
aes(xintercept = avg_price, colour = Gender),
linetype = "dashed",
size = 1
) #Добавляем средние цены продажи по полу
Boxplot
Этот тип графика также вывожу с основными настройками и с обозначение средних значений цен по мужским и женским футболкам
ggplot(df, aes(x=Gender,y = Price,fill=Gender)) +
geom_boxplot(outlier.color = "red", outlier.size = 5) + #Выделяем выбросы
geom_hline(data = mean_price,
aes(yintercept = avg_price, colour = Gender),
linetype = "dashed",
size = 1) + #Добавляем средние значения цен по полу
scale_fill_manual(values = c("#FFCCCC","#99CCFF"))+ #Задаем свой набор цветов заливки
scale_color_manual(values = c("red", "black")) #Задаем свой набор цветов линий средних значений
Можно разделить по полу и размерам
ggplot(df, aes(x=interaction(Gender,Size),y = Price,fill=Gender)) +
geom_boxplot()+
theme(axis.text.x = element_text(angle=45,size=10))+ #Задаем размер и угол наклона обозначений по оси x
scale_fill_manual(values = c("#FFCCCC","#99CCFF"))
Вывод графика в форме Violin хорош тем, что он показывает плотность вероятности данных при различных значениях. Это дает представление о форме распределения данных
Одномерное исследование категориальной переменной
Когда мы исследуем категориальную переменную, мы можем взглянуть на две вещи, либо частоты категорий или пропорции. Визуализация категориальной переменной может быть выполнена двумя способами: либо гистограммой, либо столбчатой диаграммой. По сути, это одно и то же. Просто информация представлена в другом формате. Далее будем работать со столбчатой диаграммой. Посмотрим распределение женских футболок по размерамggplot(data = df %>% filter(Gender =='Female'), mapping = aes(x= Size)) +
geom_bar() +
geom_text(aes(label = ..count..), stat = "count", vjust = 1.5,colour = "white")
Выведем диаграмму в процентах
ggplot(data = df %>% filter(Gender =='Female'), mapping = aes(x= Size)) +
geom_bar(aes(y=..count../sum(..count..))) +
scale_y_continuous(labels = scales::percent_format())
ggplot(data = df , mapping = aes(x= Gender,fill=Gender)) +
geom_bar(position="dodge") +
scale_fill_manual(values =c("#FF3399","#3399FF"))
Распределение по полу и по размерам
ggplot(data = df , mapping = aes(x= Size,fill=Gender)) +
geom_bar(position="dodge") +
scale_fill_manual(values =c("#FF3399","#3399FF"))
Визуализация взаимосвязи между двумя числовыми переменными
Для примера взаимосвязи между двумя непрерывными переменными рассмотрим новый датафрейм - стоимость аренды магазина в зависимости от его месячной проходимости. Понятно, что проходимость, это не единственный параметр, определяющий стоимость аренды, но стоит предположить, что он тем не менее, является определяющим.
df <- read_excel("ShopRent.xlsx")
df$City <- as.factor(df$City)
head(df)
# A tibble: 6 x 3
City Visit Rent
<fct> <dbl> <dbl>
1 City5 3380 2672
2 City2 5448 4183
3 City3 1903 1598
4 City6 4496 3550
5 City6 4599 3665
6 City6 1399 1279
str(df)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 100 obs. of 3 variables:
$ City : Factor w/ 6 levels "City1","City2",..: 5 2 3 6 6 6 1 1 4 2 ...
$ Visit: num 3380 5448 1903 4496 4599 ...
$ Rent : num 2672 4183 1598 3550 3665 ...
В датафрейме находятся 100 наблюдений, представляющих посещаемость (Visit) и стоимость аренды в условных единицах (Rent) в 100 магазинах, расположенных в шести городах. Попробуем графически определить, если зависимость между арендой и посещаемостью.
Для выявления связи между двумя непрерывными числовыми переменными используется диаграмма рассеяния, в пакете ggplot2 для этого используется функция geom_point, которую мы прибавляем к базовому слою.
geom_point()
Как видим по графику, зависимость определенно есть. Можем проверить с помощью теста на корреляцию. Для
этих целей мы воспользуемся функцией cor.test(). Синтаксис этой функции очень
прост. Этой функции надо передать имя первого из сопряженных векторов и имя
второго из сопряженных векторов. Дальше необходимо указать метод вычисления
коэффициента корреляции, то есть тип коэффициента корреляции. В
качестве метода вычисления коэффициента корреляции, то есть типа коэффициента
корреляции, будем использовать пирсоновский коэффициент корреляции, то есть
обычную линейную корреляцию.
cor.test(x=df$Visit,y=df$Rent,method = "pearson")
Pearson's product-moment correlation
data: df$Visit and df$Rent
t = 14.28, df = 98, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
0.7458058 0.8767278
sample estimates:
cor
0.8218337
По результатам теста мы видим, что между посещаемостью и арендной платой существует статистически значимая положительная корреляция. Поэтому попробуем построим линию регрессии с доверительной зоной при
помощи пакета ggplot. Для этого добавим на график geom_smooth.
Smooth — сглаживать. Это geom, который строит разного вида зависимости. В данном
случае мы используем метод «Линейная модель». geom_smooth сразу построит нам и
линию регрессии, и ее доверительную зону.
ggplot(df, aes(x = Visit, y = Rent)) +
geom_point()+
geom_smooth(method="lm")
Визуализация отношений между двумя категориальными переменными
У нас есть данные о дневных продажах мужских и женских футболок.
df1<- mutate(df1,Date=as.Date(Date),
Gender=factor(Gender,order = TRUE, levels=c('Female','Male')),
Wday = factor(wday(Date,week_start =1)))
head(df1)
# A tibble: 6 x 8
Date Gender Category ProdCode Size Sale Price Wday
<date> <ord> <chr> <chr> <chr> <dbl> <dbl> <fct>
1 2019-06-01 Female T-shirt TSSQ55265 S 1 999 6
2 2019-06-01 Male T-shirt TSSQ54736 M 1 849 6
3 2019-06-01 Female T-shirt TSSQ60427 L 1 3999 6
4 2019-06-01 Male T-shirt TSSQ45158 S 1 1899 6
5 2019-06-01 Female T-shirt TSSQ45162 XS 1 1899 6
6 2019-06-01 Female T-shirt TSSQ51697 XL 1 999 6
И мы хотим увидеть, сколько продаж существует
для комбинация каждого пола и дня недели. Для этого создадим кросс-таблицу.
cross_tab
Wday
Gender 1 2 3 4 5 6 7
Female 83 51 62 42 52 121 101
Male 80 79 99 67 76 241 146
Можно просто
использовать эту кросс-таблицу, чтобы увидеть, как соотносятся продажи мужских и женских футболок по дням недели.Но если мы хотим визуализацию, то проделаем еще несколько преобразований.
Пусть название строк - это пол, дни недели - это названия
столбцов. С помощью функции expand.grid создаем столбцы, которые представляют собой комбинации пола и дня
недели. Получаем датафрейм с двумя переменные, переменную
один и переменную два. Переменная один - переменная пол, два - день
недели. В качестве третьей переменной вставляем количество продаж.
Gender <- rownames(cross_tab)
Weekday <- colnames(cross_tab)
df2 <- expand.grid(Gender,Weekday)
Count <- as.vector(cross_tab)
df2$Count <- Count
head(df2)
Var1 Var2 Count
1 Female 1 83
2 Male 1 80
3 Female 2 51
4 Male 2 79
5 Female 3 62
6 Male 3 99
Теперь наши данные
готовы к визуализации.
Многомерные диаграммы
Были рассмотрены одномерные и двумерные распределения, где была одна и две переменные соответственно. Но часто бывает потребность оценить распределение по большему количеству переменных и таким образом мы переходи в область многомерных распределений и многомерных диаграмм. Вернемся к наши данным по продажам мужских и женских футболок. В этих данных можно обнаружить три измерения - пол, размер и цена. Попробуем разобраться в том, есть ли зависимости между ними. Например что происходит с ценой футболок по мере увеличения размера, стоит предположить, что цена будет расти, но насколько отличается эластичность цены по отношению к размеру в зависимости от пола. Вернемся к нашему датафрейму
# A tibble: 6 x 8
Date Gender Category ProdCode Size Sale Price Wday
<date> <ord> <chr> <chr> <chr> <dbl> <dbl> <fct>
1 2019-06-01 Female T-shirt TSSQ55265 S 1 999 6
2 2019-06-01 Male T-shirt TSSQ54736 M 1 849 6
3 2019-06-01 Female T-shirt TSSQ60427 L 1 3999 6
4 2019-06-01 Male T-shirt TSSQ45158 S 1 1899 6
5 2019-06-01 Female T-shirt TSSQ45162 XS 1 1899 6
6 2019-06-01 Female T-shirt TSSQ51697 XL 1 999 6
Построим диаграмму без деления по полу с линией регрессии
ggplot(data = df1, mapping = aes(x= as.numeric(df1$Size), y = Price))+
geom_point() + geom_smooth(method="lm", se= FALSE)
geom_point() + geom_smooth(method="lm", se= FALSE)
Как видим, есть хорошо заметный рост цены при увеличении размера, посмотрим, есть ли различия по полу
ggplot(data = df1, mapping = aes(x= as.numeric(df1$Size), y = Price,col = Gender))+
geom_point() + geom_smooth(method="lm", se= FALSE)+
scale_color_manual(values=c("#FF3399","#3399FF"))
Видно, что есть небольшое различие в эластичности в зависимости от пола, по мужским футболкам рост наблюдается чуть более крутой.
ggplot(data = df1, mapping = aes(x= as.numeric(df1$Size), y = Price,col = Gender))+
geom_point() + geom_smooth(method="lm", se= FALSE)+
scale_color_manual(values=c("#FF3399","#3399FF"))
Видно, что есть небольшое различие в эластичности в зависимости от пола, по мужским футболкам рост наблюдается чуть более крутой.
Комментариев нет:
Отправить комментарий