Одномерные диаграммы рассеяния (1-D scatter plots) представляют собой один из вариантов графического представления распределений количественных переменных. Точки, соответствующие значениям исследуемой переменной, изображаются на таких графиках вдоль единственной числовой оси. При необходимости визуализировать свойства небольших выборок одномерные диаграммы рассеяния будут отличной альтернативой диаграммам размахов. В англоязычной литературе одномерные диаграммы рассеяния называют также strip charts или strip plots, что можно перевести как "ленточные диаграммы" (не путать с этим и этим). Это название происходит от характера расположения точек на графике - они как бы выстраиваются в "ленты" (см. ниже). Реже такие графики называют еще "точечными диаграммами Уилкинсона" (см. здесь, а также оригинальную статью Wilkinson L. (1999) Dot plots. The American Statistician 53(3): 276-281).

В системе R для построения одномерных диаграмм рассеяния служит функция stripchart(). В качестве примера используем ранее рассмотренные данные по эффективности шести инсектицидных средств. Загрузим таблицу с данными в рабочую среду R:

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

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

stripchart(InsectSprays$count, method = "stack")




В приведенной выше команде помимо переменной, для которой строится график (InsectSprays$count), был использован также аргумент method (метод) со значением "stack". Этот аргумент контролирует характер расположения точек на графике; при значении "stack" ("стопка") наблюдения с одинаковыми значениями укладываются друг над другом, образуя фигуры, напоминающие ленты (отсюда название strip chart - см. выше). Следует отметить, что по умолчанию аргумент method принимает значение "overplot" (от over - поверх, и plot - рисовать), что приводит к простому наслоению точек с одинаковыми значениями друг на друга:

stripchart(InsectSprays$count, method = "overplot")



Конечно, полученный рисунок имеет мало смысла для рассматриваемых данных, но в некоторых ситуациях метод "overplot" может оказаться полезным.

В таблице InsectSprays хранятся данные по эффективности шести видов инсектицидов. Мы можем использовать это обстоятество и изобразить на одном графике распределения значений count для каждого из инсектицида. Для этого нужно будет сообщить функции stripchart(), что значения переменной count сгруппированы по уровням фактора spray:

stripchart(InsectSprays$count ~ InsectSprays$spray,
       xlab = "Количество выживших насекомых",
       ylab = "Инсектицид",
       method = "stack")



Используя аргумент vertical со значением TRUE, мы можем перевернуть приведенный график так, что по оси X будут отображены названия инсектицидов, а по оси Y - количество выживших насекомых:

stripchart(InsectSprays$count ~ InsectSprays$spray,
       ylab = "Количество выживших насекомых",
       xlab = "Инсектицид",
       vertical = TRUE,
       method = "stack")



Очень полезным методом функции stripchart() является "jitter" (дословно переводится как "дрожь"), который позволяет вносить случайный шум в расположение точек на графике. Количество шума задается при помощи одноименного аргумента, например:

stripchart(InsectSprays$count ~ InsectSprays$spray,
       ylab = "Количество выживших насекомых",
       xlab = "Инсектицид",
       vertical = TRUE,
       method = "jitter",
       jitter = 0.1,
       pch = 1, col = "blue")


Обратите внимание на то, что в приведенном выше коде были указаны также такие параметры, как форма маркеров (аргумент pch) и их цвет (аргумент col) (подробнее о настройке внешнего вида маркеров см. здесь).

Полученный график очень наглядно демонстрирует разброс наблюдений в каждой экспериментальной группе и позволяет сделать определенные предварительные заключения по поводу эффективности исследованных инсектицидов (в частности, похоже, что препараты C, D и E обладают наиболее высокой эффективностью, т.к. вызывают гибель большего количества насекомых, чем при обработке растений другими препаратами). Однако мы можем пойти еще дальше и изобразить на этом же графике средние значения количества выживших насекомых в каждой группе и их соответствующие стандартные отклонения. Для этого придется выполнить некоторые дополнительные вычисления и применить дополнительные графические функции.

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

means <- tapply(InsectSprays$count, InsectSprays$spray, FUN = mean)
means
   A    B    C    D    E    F 
14.5 15.3  2.1  4.9  3.5 16.7

Аналогичным образом рассчитаем стандартные отклонения для каждой группы:

SDs <- tapply(InsectSprays$count, InsectSprays$spray, FUN = sd)
SDs
  A   B   C   D   E   F 
4.7 4.3 2.0 2.5 1.7 6.2

Теперь добавим рассчитанные средние значения на график в виде небольших горизонтальных линий. Добавить произвольную линию на график позволяет функция segments() (сегменты; подробнее см. ?segments). Поскольку у нас имеется шесть групп, функцию segments() необходимо будет применить шесть раз. Для ускорения процесса создадим цикл при помощи оператора for:

for(i in 0:6){
segments(x0 = 0.8+i,
      y0 = means[1+i],
   x1 = 1+i,
  y1 = means[1+i], lwd = 3, lend = "square")
  }



Добавить "усы" в виде ±1 SD к полученным линиям-средним можно при помощи функции arrows() (подробнее см. ?arrows):

arrows(c(0.9, 1.9, 2.9, 3.9, 4.9, 5.9), means+SDs,
    c(0.9, 1.9, 2.9, 3.9, 4.9, 5.9), means-SDs,
    angle = 90, code = 3, length = 0.05, lwd = 1, lend = "square")



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

Более подробно работа с функциями segments(), arrows() и оператором for, использованными в рассмотренном примере, будет обсуждена в последующих сообщениях.

--
Создано при помощи Pretty R на сайте inside-R.org

5 Комментарии

Анонимный написал(а)…
Спасибо, очень интересно. Только там кажется опечатка: написано "в частности, похоже, что препараты C, В и E обладают наиболее высокой эффективностью", но похоже, что C , D и Е.
Sergey Mastitsky написал(а)…
Да, действительно опечатка. Спасибо, исправил.
Анонимный написал(а)…
Сергей, спасибо Вам за статью.
К сожалению не нашел на Вашем сайте материала по двумерным диаграммам рассеяния, поэтому задам интересующий меня вопрос здесь.
Необходимо нарисовать двумерную диаграмму рассеяния по результатам факторного анализа (всего два фактора). Удалось построить диаграмму с помощью функции plot(), однако необходимо отобразить имена переменных над каждой из точек. Как это сделать?

А ещё, может быть не в тему, но хотелось бы выразить пожелание. Очень не хватает материала по многомерной статистике: факторный, кластерный анализ, многомерное шкалирование, множественная регрессия, моделирование структурными уравнениями. Есть ли у Вас в перспективе изложить эту информацию на своем сайте? Спасибо.
Sergey Mastitsky написал(а)…
До статей по базовым графическим возможностям R можно добраться, выбрав соответствующую тему в облаке меток (см. под полем поиска по сайту). Про обычные диаграммы рассеяния можно, в частности, почитать здесь: http://r-analytics.blogspot.de/2011/10/r-plot.html

Ваше пожелание по поводу рассмотрения перечисленных методов полностью разделяю. Большинство из перечисленного в планах, но, к сожалению, из-за хронической нехватки времени на все рук не хватает. В ближайшее время я собираюсь продолжить тему общих линейных моделей и, в частности, "поговорить" о проблеме множественных сравнений, о ковариационном анализе и, позднее, перейти к огромной теме множественного регрессионного анализа. Подписывайтесь на рассылку, чтобы быть в курсе происходящего!
Sergey Mastitsky написал(а)…
Ах, да: метки к точкам на графике можно легко добавить с помощью функции text() - посмотрите примеры в ее справочном файле, а также здесь:
http://www.statmethods.net/advgraphs/axes.html
Новые Старые