от мыши до слона

Apr 19, 2014 03:53

Встроенные в R данные Animals содержат данные о весе тела и весе мозга для 28 видов животных.

>library(MASS) #чтобы сделать данные доступными
Как обычно, рекомендуется перед работой посмотреть на структуру данных:
> str(Animals)
'data.frame': 28 obs. of 2 variables:
$ body : num 1.35 465 36.33 27.66 1.04 ...
$ brain: num 8.1 423 119.5 115 5.5 ...

Функция plot(), примененая к Animals, распечатает кореллограмму (scatterplot), на которой координата x будет соответствовать первой колонке (вес тела), а координата y - второй (вес мозга).
>plot(Animals)


Как видим, из-за большого разброса (прежде всего веса тела) такой график крайне непоказателен. Самый стандартный способ преодолеть перекос данных - это логарифмическое преобразование.
Тут нам повезло, и можно преобразовать сразу все данные в таблице:
> Animals.log = log(Animals)
В иных случаях, конечно, преобразовывать нужно отдельные колонки, вроде Animals.log$brain = log(Animals$brain)
Чтобы получить более красивую графику, чем получаем функцией plot(), нужно использовать библиотеку ggplot2:
> install.packages('ggplot2') #если еще не установлена
> library(ggplot2)
> ggplot(Animals.log, aes(x = body, y = brain)) + geom_point()


Такой вариант, правда, не вполне удовлетворителен по той причине, что значения на шкалах теперь тоже отображают трансформированные данные вместо правильных. Иногда это нормально (если речь идет о величине вроде частоты слова), но вес все хотели бы видеть именно в килограммах. Есть несколько разных способов бороться с этой проблемой. Самый простой - использовать десятичный логарифм, для которой в ggplot2 есть отдельная функция. Возвращаемся к таблице Animals, мы ее не портили!
> ggplot(Animals, aes(x = brain, y = body)) + geom_point() + scale_x_log10() + scale_y_log10()


Отметки на осях теперь отображают килограммы, а не логарифм от килограммов.

По умолчанию графика выводится в некое графическое окно, которое строится данной программой.
Однако вывод можно перенаправить на другое графическое устройство, а именно в файл.
Общую схему можно проиллюстрировать такими командами:
> png('Animals_cor.png')
> ggplot(Animals, aes(x = brain, y = body)) + geom_point() + scale_x_log10() + scale_y_log10()
> dev.off()
null device
1

На второй позиции, конечно, может быть любая другая графическая команда. Обязательно необходима третья команда, закрывающая графическое устройство! Что касается первой команды, то в ней нет полного пути к файлу. Если у вас только один файл, можно указать полный путь, например, png('D:/MyRFiles/Animals_cor.png'). Более жизненная схема другая - вы заранее указываете рабочую директорию, из которой происходит чтение файлов и куда файлы записываются. Вот как указать и посмотреть рабочую директорию:
> setwd("D:/MyRFiles")
> getwd()
[1] "D:/MyRFiles"
Я еще нередко получаю список файлов в рабочей директории:
> list.files('.')
[1] "2hist.png" "2histograms" "Animals_cor" "Animals_cor.png"
[5] "BNCpronouns.R" "Surnames.R"

Разумная задача - добавить текст (названия зверей).
К сожалению, текст не получается объединить с имеющимся графиком. Если бы не логарифмическое шкалирование, можно было бы подобрать некую константу (скажем, 0.1), и каждую подпись располагать на 0.1 выше, чем точка. Вот как это выглядело бы с логарифмированной таблицей Animals.log (базовый график удобнее сохранять в переменную, вектор названий можно получить командой row.names(Animals.log), еще мы здесь мы для ясности задаем имена осей функцией labs()):
> pl0 = ggplot(Animals.log, aes(x = brain, y = body)) + geom_point()
> pl0 + geom_text(aes(y = brain + 0.1, label = row.names(Animals.log)), size = 3, vjust = 0) +
+ labs(x = 'log body', y = 'log brain')
Конечно, некоторые названия находят друг на друга и по-хорошему с этим графиком еще нужно поработать (можно хитрить с расположением подписей, можно просто выбросить часть данных; еще практикуется нанесение подписей только к части объектов), однако общий принцип, думаю, продемонстрирован вполне ясно.


В сочетании с scale_y_log10() это не работает: нижние подписи в результате будут далеко от точек, а верхние наедут на точки.


Самый простой выход из положения - это вообще убрать точки. Для приблизительного графического представления точки совершенно не обязательны.


Еще одна опция - добавить модель, сглаживающую данные.
Примеры:
#линейная модель, соответственно, добавляем прямую
> pl+ stat_smooth(method = lm)


# нелинейная модель
> pl+ stat_smooth(method = loess)


Чтобы статистически оценить корреляцию, проще всего использовать функцию cor.test():
> cor.test(Animals$brain, Animals$body)

Pearson's product-moment correlation

data: Animals$brain and Animals$body
t = 6.3451, df = 26, p-value = 1.017e-06
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
0.5730723 0.8929041
sample estimates:
cor
0.7794935

p-value практически равно нулю, корреляция достаточно сильная (0.7794935).
Правда, для применения дефолтного метода тестирования корреляции (Пирсон, справку можно посмотреть, вызывав ?cor.test) нужна нормальность векторов.
Она проверяется командой shapiro.test():
> shapiro.test(Animals$body)

Shapiro-Wilk normality test

data: Animals$body
W = 0.9847, p-value = 0.9433

Как видим, тут очень большой p-value. Это означает, что нулевую гипотезу о том, что распределение равно нормальному, совершенно невозможно отбросить, короче говоря, распределение нормальное.
Распределение Animals$brain тоже нормальное.

Степень нормальности можно также оценивать графически. Любой графический метод отображения распределения (гистограмма, боксплот, график плотности) дает некоторое представление о нормальности; более прямой способ оценки - это квантиль-квантильный график (QQ plot), см. подробнее скажем тут: http://r-analytics.blogspot.ru/p/blog-page_06.html
> qqnorm(Animals$body)
> qqline(Animals$body)


r

Previous post Next post
Up