Введение

Сегодня будет лекция для тех, кого родители не отдали в художественную школу, но кто очень-очень хочет рисовать красивые картинки.

На самом деле визуализация данных – это основа основ любого анализа, так как лучше всего мы воспринимаем информацию именно глазами. И просто больно смотреть на скудные стандартные графики из R или кривые графики из MS Excel в дипломных работах студентов МГУ. Поэтому не расстраивайте меня и рисуйте в важных работах красиво. А сегодня я вас этому научу.

У нас будет один супер-важный пакет, но пользоваться мы будем им только во второй части лекции.

library(ggplot2) # Самый важный пакет для визуализации!

Данные для рисования

В искусстве визуализации все начинается не с полотна, но с набора данных. Мы будем исследовать несколько датасетов. Первый – mtcars – данные о характеристиках 32 автомобилей из журнала Motor Trend за 1974.

Хорашая идея в том, чтобы сразу посмотреть на 4 характеристики нашего датасета:

  1. Размерность (сколько строк и сколько переменных).
  2. Начало таблицы.
  3. str – тип каждой переменной
  4. summary – краткая сводка по каждой переменной
dim(mtcars)
## [1] 32 11
head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
str(mtcars)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
summary(mtcars)
##       mpg             cyl             disp             hp       
##  Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
##  1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
##  Median :19.20   Median :6.000   Median :196.3   Median :123.0  
##  Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
##  3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
##  Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  
##       drat             wt             qsec             vs        
##  Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  
##  1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  
##  Median :3.695   Median :3.325   Median :17.71   Median :0.0000  
##  Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  
##  3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  
##  Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  
##        am              gear            carb      
##  Min.   :0.0000   Min.   :3.000   Min.   :1.000  
##  1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  
##  Median :0.0000   Median :4.000   Median :2.000  
##  Mean   :0.4062   Mean   :3.688   Mean   :2.812  
##  3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  
##  Max.   :1.0000   Max.   :5.000   Max.   :8.000

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

Mazda RX4

Второй – diamonds – из пакета ggplot2, стоимость бриллиантов в зависимости от их цвета, качества огранки, размеров и ясности (clarity):

dim(diamonds)
## [1] 53940    10
head(diamonds)
##   carat       cut color clarity depth table price    x    y    z
## 1  0.23     Ideal     E     SI2  61.5    55   326 3.95 3.98 2.43
## 2  0.21   Premium     E     SI1  59.8    61   326 3.89 3.84 2.31
## 3  0.23      Good     E     VS1  56.9    65   327 4.05 4.07 2.31
## 4  0.29   Premium     I     VS2  62.4    58   334 4.20 4.23 2.63
## 5  0.31      Good     J     SI2  63.3    58   335 4.34 4.35 2.75
## 6  0.24 Very Good     J    VVS2  62.8    57   336 3.94 3.96 2.48
str(diamonds)
## 'data.frame':    53940 obs. of  10 variables:
##  $ carat  : num  0.23 0.21 0.23 0.29 0.31 0.24 0.24 0.26 0.22 0.23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num  61.5 59.8 56.9 62.4 63.3 62.8 62.3 61.9 65.1 59.4 ...
##  $ table  : num  55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int  326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num  3.95 3.89 4.05 4.2 4.34 3.94 3.95 4.07 3.87 4 ...
##  $ y      : num  3.98 3.84 4.07 4.23 4.35 3.96 3.98 4.11 3.78 4.05 ...
##  $ z      : num  2.43 2.31 2.31 2.63 2.75 2.48 2.47 2.53 2.49 2.39 ...
summary(diamonds)
##      carat               cut        color        clarity     
##  Min.   :0.2000   Fair     : 1610   D: 6775   SI1    :13065  
##  1st Qu.:0.4000   Good     : 4906   E: 9797   VS2    :12258  
##  Median :0.7000   Very Good:12082   F: 9542   SI2    : 9194  
##  Mean   :0.7979   Premium  :13791   G:11292   VS1    : 8171  
##  3rd Qu.:1.0400   Ideal    :21551   H: 8304   VVS2   : 5066  
##  Max.   :5.0100                     I: 5422   VVS1   : 3655  
##                                     J: 2808   (Other): 2531  
##      depth           table           price             x         
##  Min.   :43.00   Min.   :43.00   Min.   :  326   Min.   : 0.000  
##  1st Qu.:61.00   1st Qu.:56.00   1st Qu.:  950   1st Qu.: 4.710  
##  Median :61.80   Median :57.00   Median : 2401   Median : 5.700  
##  Mean   :61.75   Mean   :57.46   Mean   : 3933   Mean   : 5.731  
##  3rd Qu.:62.50   3rd Qu.:59.00   3rd Qu.: 5324   3rd Qu.: 6.540  
##  Max.   :79.00   Max.   :95.00   Max.   :18823   Max.   :10.740  
##                                                                  
##        y                z         
##  Min.   : 0.000   Min.   : 0.000  
##  1st Qu.: 4.720   1st Qu.: 2.910  
##  Median : 5.710   Median : 3.530  
##  Mean   : 5.735   Mean   : 3.539  
##  3rd Qu.: 6.540   3rd Qu.: 4.040  
##  Max.   :58.900   Max.   :31.800  
## 

Базовая визуализация

Есть несколько супер-базовых видов графиков, которые R поддерживает by default.

Простой график

Он же scatter plot. Когда мы просто рисуем точки на плоскости. Следующий две команды эквивалентны, они рисуют зависимость расхода топлива от объема двигателя:

#plot(mtcars$disp, mtcars$mpg) # plot(x, y)
plot(data=mtcars, mpg ~ disp)  # plot(data=тут ваш дата фрейм, y ~ x)

Но пускать такой график в диплом нельзя, нужны стандартные украшательства:

plot(data=mtcars, mpg ~ disp, 
  main="Расход топлива от объема двигателя", 
  xlab="Объем, куб. дюьймы", 
  ylab = "Миль на галлон",
  pch=3) # Треугольники!

Похоже, что расход топлива зависит от объема двигателя (внезано!). Добавим прямо сюда линию из линейной МНК-модели?

plot(data=mtcars, mpg ~ disp, 
  main="Расход топлива от объема двигателя", 
  xlab="Объем, куб. дюьймы", 
  ylab = "Миль на галлон",
  pch=5) # Ромбики!
abline(lm(data=mtcars, mpg ~ disp))

Как визуализировать еще одно измерение? Нет, трехмерные графики – плохо, так как их очень тяжело читать. Допустим, я хочу на этот же график наложить количество цилиндров, не выходя из 2d. Как? Но сначала небольшой экскурс в дискретные данные.

mtcars$cyl
##  [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
as.factor(mtcars$cyl)
##  [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
## Levels: 4 6 8

Фактор – это не число, а переменная, принимающая всего три возможных значения: 4, 6 или 8.

А еще глянем на полезную команду subset:

mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
subset(mtcars, cyl==4)
##                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230       22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Volvo 142E     21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
subset(mtcars, cyl==4 & am==1 & mpg>30 | mpg<11)
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2

Теперь приступим к рисованию.

plot(data=mtcars, mpg ~ disp, 
  main="Расход топлива от объема двигателя", 
  xlab="Объем, куб. дюьймы", 
  ylab = "Миль на галлон",
  pch=2,
  col=as.factor(cyl)) # Точки разных цветов!
# И свой МНК для каждого класса!
abline(lm(data=subset(mtcars, cyl==4), mpg ~ disp), col=1)
abline(lm(data=subset(mtcars, cyl==6), mpg ~ disp), col=2)
abline(lm(data=subset(mtcars, cyl==8), mpg ~ disp), col=3)

Едем дальше?

Pontiac

Я не знаю, какой график строить!

Стандартная головная боль: у нас есть 11 переменных и нет никакого понятия о том, как они все связаны. Грубое решение – построить все от всего и долго медитировать.

pairs(mtcars, main="Много графиков!")

Boxplot или ящик-с-усами

Как сравнить два распределени. Скажем, потребление топлива для аКПП и ручной коробки. Для этого нам нужен boxplot!

boxplot(data=mtcars, mpg ~ am, main="Ящики с усами", xlab="Ручная коробка?", ylab="MPG")

Очень хорошо бы понять, что скрывается за этими черточками. Обычно, ящик ограничивает 1 и 3 вартиль, черта – медиана. А усы – что-то вроде “доверительного интервала”. Тут такая эвристика: если точка лежит вне уса, то она какая-то очень странная. Ее нужно уделить особое внимание.

Проверим на равенство средних? Мы же не только картинки пришли смотреть, так?

t.test(subset(mtcars, am==0, mpg), subset(mtcars, am==1, mpg))
## 
##  Welch Two Sample t-test
## 
## data:  subset(mtcars, am == 0, mpg) and subset(mtcars, am == 1, mpg)
## t = -3.7671, df = 18.332, p-value = 0.001374
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -11.280194  -3.209684
## sample estimates:
## mean of x mean of y 
##  17.14737  24.39231

Welch – это хороший аналог t-теста, который более устойчив к разным дисперсиям и разным размерам выборок.

Какие выводы?

Lincoln

Пироги

Оговрка: пироги (pie chart) – это плохо. Они не понятны, не наглядны, ничего не характеризуют. Лучше их не использовать. Но они такие популярные. В этом мини-руководстве я приведу только один пример, чтобы никто ничего не запомнил.

Но сначала полезная функция table – возвращает число наблюдений каждого типа:

table(mtcars$cyl)
## 
##  4  6  8 
## 11  7 14
pie(table(mtcars$cyl), main = "Пироги настолько плохи,\n что не заслуживают заголовка")

Если кратко, то пирог он… он как этот фиат.

Fiat

Гистограммы

Вы это уже все знаете.

hist(mtcars$qsec, breaks = 10)

Ну может пара новых фишек – штриховочка и столбцы вручную:

hist(mtcars$qsec, breaks = c(10,18,19,25), density = 10, col="darkgreen")

Хотя я не представляю, зачем вам это может понадобиться.

Mercedes

ggplot2

Знания юнлинга

В чем проблема всех этих графиков? В том, что они некрасивые. Пакет ggplot2 решает эту проблему и проблему недостаточной гибкости и низкого функционала. Его две стандартные функции: qplot и ggplot. Первая более “умная” и может многое сделать за вас, но вторая умеет больше и более гибкая. Ее мы и изучим, тогда в qplot легко можно разобраться.

Команда ggplot создает холст, на котором нет ничего. ее нужно передать датасет и внутри специальной функции aes параметры для рисования: координаты, цвета, заливки и т.д.

# ggplot() # Вот, все падает с ошибкой.
# ggplot(mtcars, aes(x=qsec, y=mpg)) # Даже так

Дальше ggplot ожидает, что мы скажем, что именно хотим нарисовать. Все возможные варианты начинаются с префикса geom_ и дописываются через знак +:

ggplot(mtcars, aes(x=qsec, y=mpg)) + geom_point()

Хотите линию? Легко:

ggplot(mtcars, aes(x=qsec, y=mpg)) + geom_line()

Кто догадался, как сделать и то, и то?

ggplot(mtcars, aes(x=qsec, y=mpg)) + geom_line() + geom_point()

Нужен боксплот?

ggplot(mtcars, aes(x=factor(cyl), y=mpg)) + geom_boxplot()

Нужна гистограмма?

ggplot(mtcars, aes(x=mpg)) + geom_histogram(binwidth=2)

Знания падавана

Более продвинутые знания освоим на большом датасете diamonds:

ggplot(diamonds, aes(x=carat, y=price)) + geom_point()

Что можно сказать про эти данные?

Что на этом графике плохо? Да почти все.

  1. Точки слишком плотно, нужно добавить прозрачность.
  2. Куча измерений, а мы отразили только два.
  3. Плотная группировка у нуля и странная нелинейная зависимость. Может попробовать логарифмические шкалы?

Добавим все сразу?

ggplot(diamonds, aes(x=carat, y=price, col=color)) + 
  geom_point(alpha=1/6) +  # Прозрачность
  scale_x_log10(breaks=1:8) + # Логарифмическая ось x и деления от 1 до 8
  scale_y_log10(breaks=c(250,500,1000,2500,5000,10000, 20000)) # И для оси y

Вернемся к обычным осям и разукрасим по качеству огранки. Но добавим немного сглаживающих линий:

ggplot(diamonds, aes(x=carat, y=price, col=cut)) + 
  geom_point(alpha=0.6) +
  geom_smooth(method="lm")

Или даже так:

ggplot(diamonds, aes(x=carat, y=price, col=cut)) + 
  geom_point(alpha=0.6) +
  geom_smooth()

Мы можем даже добавить еще одно измерение! (Это уже плохая визуализация. Рисуем, потому что можем.)

ggplot(diamonds, aes(x=carat, y=price, col=color, shape=cut)) + 
  geom_point(alpha=0.6)

Знания рыцаря-джедая

Боксплоты:

ggplot(diamonds, aes(x=color, y=price)) + geom_boxplot()

А теперь добавим красоты:

ggplot(diamonds, aes(x=color, y=price, fill=color)) + 
  geom_boxplot() + 
  scale_y_log10() +
  ggtitle("Красивый боксплот")

И теперь еще круче – добавим точки:

ggplot(diamonds, aes(x=color, y=price, color=color)) + 
  geom_boxplot() + 
  geom_point(alpha=1/10)+
  scale_y_log10() +
  ggtitle("Красивый боксплот - 2")

Проблема: точки слились и ничего не видно. Решение: jitter – эта штука немного раскидывает точки в сторону.

ggplot(diamonds, aes(x=color, y=price, color=color)) + 
  geom_boxplot() + 
  geom_point(alpha=1/15, position = position_jitter())+
  scale_y_log10() +
  ggtitle("Красивый боксплот - 3")

Немного о гистограммах (и барплотах):

ggplot(diamonds, aes(x=price)) + 
  geom_histogram(binwidth=500)

Цвета!

ggplot(diamonds, aes(x=price, fill=color)) + 
  geom_histogram(binwidth=500)

Интересно, меняется ли доля каждого цвета по мере роста цены? Нужно добавить нормализацию:

ggplot(diamonds, aes(x=price, fill=color)) + 
  geom_histogram(binwidth=500, position = 'fill')

Знания мастера-джедая

Боксплоты хороши, но страдают от того, от чего строадает вся наука о риске: патаются в одно число запихнуть всю информацию о распределении. Поэтому вместо ящика можно нарисовать распределение.

ggplot(diamonds, aes(y=price, x=color, fill=color)) +
  geom_violin(scale='width', trim=FALSE) + 
  scale_y_log10()

Сравнить с:

ggplot(diamonds, aes(y=price, x=color, fill=color)) +
  geom_violin(scale='count', trim=FALSE) + 
  scale_y_log10()

Для странных ребят, которы презирают прямоугольные координаты:

ggplot(diamonds, aes(y=price, x=color, fill=color)) +
  geom_violin(scale='count') + 
  scale_y_log10() +
  coord_polar()

Бесмысленно? Да! Красиво? Может быть.

Вот еще полезная штука – барплот: считает сумму по заданному полю, это как гистограмма для дискретных переменных.

table(diamonds$color)
## 
##     D     E     F     G     H     I     J 
##  6775  9797  9542 11292  8304  5422  2808
ggplot(diamonds, aes(x=color)) + 
  geom_bar()

Собственно, для недискретной переменной барплот и есть гистограмма.

Цвета::

ggplot(diamonds, aes(x=color, fill=cut)) + 
  geom_bar()

ggplot(diamonds, aes(x=color, fill=cut)) + 
  geom_bar(position = 'fill')

Или так:

ggplot(diamonds, aes(x=color, fill=cut)) + 
  geom_bar(position = position_dodge()) 

Удобны бывает подсчитать не количество, а сумму по какому-либо полю. Для этого нужно добавить переменную y и stat='identity'. Скажем, суммарный вес всех бриллиантов каждого цвета из датасета.

ggplot(diamonds, aes(y=carat, x=color)) + 
  geom_bar(stat='identity')

Или еще один срез?

ggplot(diamonds, aes(y=carat, x=color, fill=cut)) + 
  geom_bar(stat='identity', position = position_dodge())

Еще пара новых украшательств:

ggplot(diamonds, aes(y=carat, x=color, fill=color)) + 
  geom_bar(stat='identity', position = position_dodge()) + 
  coord_flip() + # Вот так легко развернуть оси
  scale_fill_brewer(palette="Pastel1") # Для тех, кто устал уже от ярких цветов

Вот ссылка на другие наборы цыетов.

Построим еще один простой график график, но со всеми наворотами? Он будет строится долго и требует еще один дополнительный пакет.

library(ggExtra)
# Сохраним весь график в одну переменную
myplot <- ggplot(diamonds, aes(y=price, x=x, color=color, size=carat)) +
  geom_point(alpha=1/2) + 
  scale_y_log10() + 
  scale_x_log10(breaks=1:10) + 
  xlab('Линейный размер по оси x, мм.') + 
  ylab('Стоимость, $.') + 
  geom_rug(alpha=0.01)
#ggsave('plot.png', plot=myplot) # Сохранить график на диск
ggMarginal(myplot, type="histogram")

Частные случаи

Корреляционная матрица

Даже не буду ничего писать, все и так знают. Сразу к рисованию.

cor(mtcars)
##             mpg        cyl       disp         hp        drat         wt
## mpg   1.0000000 -0.8521620 -0.8475514 -0.7761684  0.68117191 -0.8676594
## cyl  -0.8521620  1.0000000  0.9020329  0.8324475 -0.69993811  0.7824958
## disp -0.8475514  0.9020329  1.0000000  0.7909486 -0.71021393  0.8879799
## hp   -0.7761684  0.8324475  0.7909486  1.0000000 -0.44875912  0.6587479
## drat  0.6811719 -0.6999381 -0.7102139 -0.4487591  1.00000000 -0.7124406
## wt   -0.8676594  0.7824958  0.8879799  0.6587479 -0.71244065  1.0000000
## qsec  0.4186840 -0.5912421 -0.4336979 -0.7082234  0.09120476 -0.1747159
## vs    0.6640389 -0.8108118 -0.7104159 -0.7230967  0.44027846 -0.5549157
## am    0.5998324 -0.5226070 -0.5912270 -0.2432043  0.71271113 -0.6924953
## gear  0.4802848 -0.4926866 -0.5555692 -0.1257043  0.69961013 -0.5832870
## carb -0.5509251  0.5269883  0.3949769  0.7498125 -0.09078980  0.4276059
##             qsec         vs          am       gear        carb
## mpg   0.41868403  0.6640389  0.59983243  0.4802848 -0.55092507
## cyl  -0.59124207 -0.8108118 -0.52260705 -0.4926866  0.52698829
## disp -0.43369788 -0.7104159 -0.59122704 -0.5555692  0.39497686
## hp   -0.70822339 -0.7230967 -0.24320426 -0.1257043  0.74981247
## drat  0.09120476  0.4402785  0.71271113  0.6996101 -0.09078980
## wt   -0.17471588 -0.5549157 -0.69249526 -0.5832870  0.42760594
## qsec  1.00000000  0.7445354 -0.22986086 -0.2126822 -0.65624923
## vs    0.74453544  1.0000000  0.16834512  0.2060233 -0.56960714
## am   -0.22986086  0.1683451  1.00000000  0.7940588  0.05753435
## gear -0.21268223  0.2060233  0.79405876  1.0000000  0.27407284
## carb -0.65624923 -0.5696071  0.05753435  0.2740728  1.00000000
library(reshape2)

ggplot(data = melt(cor(mtcars)), aes(x=Var1, y=Var2, fill=value)) + 
  geom_tile() + 
  scale_fill_gradient2(low = "blue", high = "red", mid = "white")

Второй вариант (сюда тоже можно добавить цвета):

library(ellipse)
plotcorr(cor(mtcars))

Третий (очень приятный, которы сочетает все):

library(corrplot)
corrplot(cor(mtcars))

corrplot(cor(mtcars), addCoef.col="black", order="AOE", tl.srt=45)

corrplot(cor(mtcars), order="AOE", method = "ellipse")

И еще огромное число параметров в ?corrplot.

Лица Чернова

Плохо:

smallmtcars <- mtcars[1:16, ]
stars(smallmtcars)

Идея:

Чернов, это ты?

Хорошо:

library(TeachingDemos)
faces(smallmtcars)

Чтение по теме

  1. Основная книга по визуализации в R:R graphics cookbook. Там есть все что нужно и еще немного больше.
  2. R Data Visualization Cookbook
  3. Не читал, но говорят, что неплохо. На русском. СТАТИСТИЧЕСКИЙ АНАЛИЗ И ВИЗУАЛИЗАЦИЯ ДАННЫХ С ПОМОЩЬЮ R.

Домашнее задание

  1. Выбрать любой набор данных. С как минимум двумя непрерывными переменными и как минимум двумя категориальными.
  2. Построить интересные графики, с помощью которых можно найти что-то интересное. Или просто построить красивые графики. Какие? На ваше усмотрение.
  3. Написать небольшие выводы, почему конкретный график хороший, если он хороший, или почему плохой, если плохой.

Примеры данных:

  1. Встроенные в R наборы данных
  2. Данные из пакета ggplot2: неплохо подходит база IMDB (movies) и статистика сна msleep
  3. Весь репозиторий данных UCI. Например, качество вина от его характеристик.