20 января 2012

Базовые графические возможности R: столбиковые диаграммы



Для создания столбиковых (= "столбчатых", реже "линейчатых"; англ. bar plots или bar charts) диаграмм в системе R служит функция barplot(). У этой функции имеется большое количество аргументов, к основным из которых относятся (подробнее см. ?barplot):
  • hight ("высота") - числовой вектор или матрица со значениями, используемыми для построения диаграммы. Если аргумент hight указан в виде вектора, то строится график из последовательно расположенных столбцов, высоты которых соответствовуют значениям этого вектора. Если hight указан в виде матрицы и аргумент beside = FALSE, то будет построена столбчая диаграмма с накоплением. Если же hight указан в виде матрицы и аргумент beside = TRUE, то столбцы диаграммы будут сгруппированы в соответствии со столбцами матрицы.
  • width ("ширина") - необязательный параметр, позволяющий регулировать ширину столбцов на диаграмме. Указывается в виде числового вектора, значения которого соотвествуют ширине столбцов.
  • space ("пространство") - величина зазора между столбцами (пропорционально их средней ширине). Может быть указан либо виде одного числа, либо в виде вектора из чисел, соотвествующих каждому столбцу диаграммы.
  • names.arg - текстовый вектор, содержащий подписи (вдоль оси OX) для каждого столбца или группы столбцов. Если этот аргумент не указан, в качестве подписей автоматически будут использованы имена элементов вектора height (если таковые имеются), либо заголовки столбцов если height представляет собой матрицу.
  • legend.text - вектор, содержащий текстовые элементы легенды графика. Этот аргумент полезен только если height является матрицей. В этом случае метки легенды должны соотвествовать строкам матрицы. Аргументу legend.text можно также присвоить значение TRUE, и тогда имена строк матрицы (если таковые имеются) будут использованы в качестве меток легенды автоматически.
  • beside - принимает логическое значение и имеет смысл только, если height является матрицей. Значение FALSE приведет к построению диаграммы с накоплением. При значении TRUE столбцы будут сгруппированы.
  • horiz - принимает логическое значение: TRUE для горизонтального расположения столбцов и FALSE - для вертикального.
  • density - числовой вектор, задающий плотность заштриховки столбцов.
  • angle - угол наклона штрихов (в градусах).
  • col - вектор цветовых кодов для столбцов или их элементов. По умолчанию столбцы закрашиваются серым цветом если height - вектор, и разными градациями серого если height - матрица.
  • border - код цвета для обводки столбцов. Если границу столбцов обводить не предполагается, можно указать border = NA.
  • ... - другие графические параметры (см., например, ?plot и ?par).

В качестве первого примера используем рассмотренные ранее данные по эффективности шести инсектицидных средств (A - F), входящие в базовую комплектацию R. Загрузим таблицу с этими данными в рабочую среду R:
data(InsectSprays)
 
InsectSprays
 
   count spray
1     10     A
2      7     A
3     20     A
4     14     A
5     14     A
6     12     A
7     10     A
8     23     A
9     17     A
10    20     A
11    14     A
12    13     A
13    11     B
14    17     B
15    21     B
...   ...   ...
 
69    26     F
70    26     F
71    24     F
72    13     F

Стоит задача отобразить средние значения количества насекомых, учтенных на экспериментальных растениях после обработки каждым инсектицидом, в виде столбиковой диаграммы. Эти средние значения можно быстро рассчитать для каждой группы при помощи функции tapply(). Результат вычислений сохраним в векторе Means:

attach(InsectSprays)
 
Means <- tapply(count, spray, mean)
 
Means
    A     B     C     D     E     F 
14.50 15.33  2.08  4.92  3.50 16.67

Для построения столбчатой диаграммы в простейшем ее виде достаточно выполнить следующую команду:

barplot(height = Means) # или просто barplot(Means)

Добавим подписи осей и закрасим столбцы диаграммы голубым цветом:

barplot(Means, col = "steelblue",
       xlab = "Инсектицид",
       ylab = "Количество выживших насекомых")


Далее продемонстрировано действие разных аргументов функции barplot(), изменяющих внешний вид диаграммы.

Изменена ширина столбцов (теперь она пропорциональна квадратному корню из высоты соответствующего столбца - аргумент width) и цвет их обводки (на красный - аргумент border):

barplot(Means, col = "steelblue",
        xlab = "Инсектицид",
        ylab = "Количество выживших насекомых",
        border = "red", width = sqrt(Means))



Столбцы имеют исходную ширину и цвет обводки, но теперь они заштрихованы (аргумент density) и изображены горизонтально (аргумент horiz):

barplot(Means, density = 20, col = "red", horiz = T,
        ylab = "Инсектицид", xlab = "Количество выживших инсекомых",
        las = 1 # аргумент las=1 заставляет названия инсектицидов
        # принять вертикальное положение
        )




Предыдущий график изменен путем увеличения зазора между столбцами (аргумент space) и измения угла наклона штрихов (аргумент angle):

barplot(Means, density = 20, angle = -45, space = 2,
        col = "red", horiz = TRUE, las = 1,
        ylab = "Инсектицид", xlab = "Количество выживших инсекомых")



Столбиковые диаграммы, подобные рассмотренным, часто используются для отображения средних значений. Однако следует помнить, что это не самый удачный способ для такого рода визуализации (подробнее см. здесь).

Построение диаграммы, где столбцы сгруппированы в соответствии с уровнями какого-либо фактора, рассмотрим на примере данных из таблицы genotype, входящей в состав пакета MASS. В эту таблицу входят данные из эксперимента, в котором были задействованы лабораторные крысы четырех разных генотипов (A, B, C, D). Выводок (Litter) от самок (Mother) каждого генотипа изолировался от матерей и отдавался на вскармливание самкам других генотипов. В конце эксперимента (на 28-й день) был измерен вес у крысят (Wt), кормившихся молоком от разных самок, с целью установить влияние генотипа на этот показатель.

Ознакомимся с данными:

library(MASS)
 
data(genotype)
 
genotype
 
   Litter Mother   Wt
1       A      A 61.5
2       A      A 68.2
3       A      A 64.0
4       A      A 65.0
5       A      A 59.7
6       A      B 55.0
7       A      B 42.0
8       A      B 60.2
9       A      I 52.5
10      A      I 61.8
11      A      I 49.5
12      A      I 52.7
13      A      J 42.0
14      A      J 54.0
15      A      J 61.0
16      A      J 48.2
17      A      J 39.6
18      B      A 60.3
19      B      A 51.7
20      B      A 49.3
...    ...    ...
58      J      J 51.5
59      J      J 53.0
60      J      J 42.0
61      J      J 54.0

Рассчитаем средние значения веса для каждой экспериментальной группы при помощи функции tapply():

means = with(genotype, tapply(Wt, list(Litter, Mother), mean))
# Функция with() позволяет указать таблицу, из которой
# функция tapply() должна брать данные для вычислений
 
# Просмотрим содержимое матрицы means: 
means
      A     B     I     J
A 63.68 52.40 54.12 48.96
B 52.33 60.64 53.92 45.90
I 47.10 64.37 51.60 49.43
J 54.35 56.10 54.53 49.06

Результатом вычислений, выполненных при помощи функции tapply(), является матрица, которую мы можем непосредственно использовать для построения столбчатой диаграммы:

barplot(means, beside = TRUE,
       col = topo.colors(4),
       legend.text = rownames(means),
       xlab = "Выводок", ylab = "Вес, г",
       ylim = c(0, 100))

В приведенном коде цвет столбцов задан при помощи функции topo.colors(), которая автоматически подбирает необходимое количество хорошо сочетающихся цветов в стиле "топографическая карта". Легенда графика включена при помощи агрумента legend.text, которому присвоены значения в виде заголовков строк матрицы means. Для того чтобы легенда не "наползла" на столбцы, пришлось несколько растянуть ось OY при помощи аргумента ylim. Результат выглядит так:



Обратите внимание на то, что для построения приведенного графика аргументу beside  было присвоено значение TRUE. Если бы мы присвоили этому аргументу значение FALSE, то получили бы столбиковую диаграмму с накоплением:

 barplot(means, beside = FALSE,
         col = topo.colors(4),
         xlab = "Выводок", ylab = "Вес, г")



К столбцам диаграмм мы можем добавить "усы", соответствующие, например, стандартным отклонениям. Стандартные отклонения легко рассчитать, используя все ту же функцию tapply() (в связке с with()):

sds = with(genotype, tapply(Wt, list(Litter, Mother), sd))
 
# Просмотрим результат:
 
sds
      A    B    I    J
A  3.27 9.37 5.32 8.76
B  5.53 5.65 5.11 7.64
I 18.10 7.12 8.62 5.37
J  5.33 3.35 8.38 5.34

Подобно ранее рассмотренному примеру, "усы" к столбцам можно добавить при помощи функции arrows():

# Сохраним диаграмму в виде самостоятельного объекта b.
# Помимо прочего, этот объект будет хранить информацию
# о высоте столбцов, что потребуется далее при добавлении
# "усов" к этим столбцам.
# Аргумент ylim в связке с функциями min(), max() и pretty()
# используется для автоматического подбора оптимального
# диапазона значений, отображаемых на оси ординат (подробнее
# см. ?min, ?max?, ?pretty):
 
b <- barplot(means, ylim = c(min(pretty(means-sds)),
             max(pretty(means+sds))),
             col = topo.colors(4),
             beside = TRUE, xpd = FALSE,
             ylab = "Вес, г", xlab = "Выводок",
             legend.text=rownames(means))
 
# Добавляем "усы":
arrows(b, means+sds, b, means-sds, angle = 90, code = 3, length = 0.05)


9 комментариев :

atner комментирует...

Можно ли сделать подписи прямо в столбиках?

Sergey Mastitsky комментирует...

Конечно. См. ?text

atner комментирует...

Ну коли так тут оперативно отвечают, то обращусь напрямую.
Итак - не понимаю, почему у меня выскакивают надписи по ординате.
Второе - сейчас попробую вывести цифровые значения в графах (через text..)

картинки в комментарий не вставляются: Ваш код HTML не может быть принят: Недопустимый тег: IMG
http://img-fotki.yandex.ru/get/9555/289408.2d7/0_83890_68361b7d_XL.png

Sergey Mastitsky комментирует...

См. мой ответ Вконтакте...

Сергей Насонов комментирует...

Добрый день. Подскажите пож. как поместить текст поверх баров, с использованием text. Не найду как задать центры баров по оси Х (что бы подписи располагались ровно по центру.)

Sergey Mastitsky комментирует...

x <- sample(seq(15, 30, 5))
midpoints <- barplot(x, ylim = c(0, 35))
text(midpoints, x+1, labels=x)

Сергей Насонов комментирует...

Сергей спасибо большое!

Pavel M комментирует...

> Means <- tapply(count, spay, mean)
Error in tapply(count, spay, mean) : object 'spay' not found
Может быть - spray?

Sergey Mastitsky комментирует...

Да, там была опечатка. Исправил, спасибо!

Отправить комментарий