Суббота, 04.04.2026, 19:28Приветствуем вас Гость | RSS
Решение задач в среде R
Главная | Дисперсионный анализ в R | Регистрация | Вход
» Меню сайта

» R практикум

» R кодинг

» Rmatem

» Опрос
Сколько вам лет?
Всего ответов: 9

» Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Дисперсионный анализ в R

Настало время перейти от описания выборок к их сравнению, а точнее к оценке статистической значимости различий между ними. Займемся дисперсионным анализом. Дисперсионный анализ применяют для изучения влияния качественных признаков на количественную переменную. В англоязычной литературе он обозначается как ANOVA (Analisis of Variances). Однофакторный дисперсионный анализ используется для определения наличия или отсутствия статистически значимой разницы между средними значениями трех или более независимых групп. Если бы нас вместо этого интересовало влияние двух переменных-предсказателей на переменную отклика, мы могли бы выполнить двусторонний дисперсионный анализ MANOVA (Multiple Analysis of Variance). Это – многомерный дисперсионный анализ, но сейчас мы им заниматься не будем.

Как выполнить односторонний дисперсионный анализ в R ?

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

В качестве примера рассмотрим, как различаются между собой по массе семь различных сортов клубники. Для простоты дадим им названия «сорт1», «сорт2» и т.д. Массы будут сгенерированы случайным образом (нормальное распределение). Эту часть скрипта мы выполним и получим датафрейм всех исходных данных.

 

# Дисперсионный анализ трех групп

set.seed(5454)

sort1 = round(rnorm(100, 11.6, 3), 1)

sort2 = round(rnorm(120, 11.4, 3.3), 1)

sort3 = round(rnorm(130, 13.4, 2.5), 1)

sort4 = round(rnorm(110, 12.8, 2.4), 1)

sort5 = round(rnorm(150, 11.5, 2.4), 1)

sort6 = round(rnorm(120, 11.1, 2.8), 1)

sort7 = round(rnorm(140, 13.5, 4.4), 1)

 


df=rbind(data.frame(sort='sort1', massa = sort1),
         
         data.frame(sort='sort2', massa = sort2),
         
         data.frame(sort='sort3', massa = sort3),
         
         data.frame(sort='sort4', massa = sort4),
         
         data.frame(sort='sort5', massa = sort5),
         
         data.frame(sort='sort6', massa = sort6),
         
         data.frame(sort='sort7', massa = sort7))

head(df) 

 

Теперь приступим к изучению полученных искусственно данных. Первое что сделаем – визуализируем эти данные. Выполнив конструкцию ниже мы получим «ящики с усами».

boxplot(massa ~ sort, df)

grid(col='black')

boxplot(massa ~ sort,df,add=T) 

И, собственно, уже что-то не так. А дело в том, что на основании визуализации этих данных мы не можем установить, а есть ли значимые отличия между группами. Максимум что можно увидеть что есть несколько столбиков которые «выделяются» из общей картины. Давайте улучшим исходный вариант следующим образом: отобразим средние значения точками и добавим доверительные интервалы:

library(ggplot2)
ggplot(df, aes(massa, sort))+
  stat_summary(fun.data = mean_cl_boot, geom = "errorbar", width = 0.1, size = 1)+
  stat_summary(fun.y = mean, geom = "point", size = 6, shape = 22, fill = "white")+
  theme_bw()+
  xlab("масса граммы")+
  ylab("сорта")

Так гораздо лучше! Во-первых, непересекающиеся доверительные интервалы подтверждают наш вывод о статистически значимых различиях. Там где группы статистически различаются доверительные интервалы не пересекаются. Но все же не понятно как сильно различаются группы? Какие группы практически не различаются или напротив различаются максимально сильно. А вот теперь настала очередь применить очень точный и очень серьезный инструмент: собственно дисперсионный анализ.

tmassa = aov(massa ~ sort, df)
summary(tmassa)
ans=TukeyHSD(tmassa)
ans

> ans
 Tukey multiple comparisons of means
 95% family-wise confidence level

Fit: aov(formula = massa ~ sort, data = df)

$sort
 diff lwr upr p adj
sort2-sort1 -0.25616667 -1.2839968 0.77166345 0.9902972
sort3-sort1 2.11223077 1.1094124 3.11504910 0.0000000
sort4-sort1 1.22027273 0.1636463 2.27689917 0.0119043
sort5-sort1 0.13233333 -0.8291137 1.09378037 0.9996508
sort6-sort1 -0.44866667 -1.4764968 0.57916345 0.8567595
sort7-sort1 2.07728571 1.0964135 3.05815788 0.0000000
sort3-sort2 2.36839744 1.2415641 3.49523074 0.0000000
sort4-sort2 1.47643939 0.3014636 2.65141519 0.0040658
sort5-sort2 0.38850000 -0.7016785 1.47867846 0.9413129
sort6-sort2 -0.19250000 -1.3416490 0.95664900 0.9989214
sort7-sort2 2.33345238 1.2261047 3.44080007 0.0000000
sort4-sort3 -0.89195804 -2.0451180 0.26120196 0.2521003
sort5-sort3 -1.97989744 -3.0465272 -0.91326772 0.0000011
sort6-sort3 -2.56089744 -3.6877307 -1.43406413 0.0000000
sort7-sort3 -0.03494505 -1.1191170 1.04922687 0.9999999
sort5-sort4 -1.08793939 -2.2053085 0.02942974 0.0622145
sort6-sort4 -1.66893939 -2.8439152 -0.49396360 0.0005869
sort7-sort4 0.85701299 -0.2771138 1.99113979 0.2789166
sort6-sort5 -0.58100000 -1.6711785 0.50917846 0.6987057
sort7-sort5 1.94495238 0.8989292 2.99097559 0.0000011
sort7-sort6 2.52595238 1.4186047 3.63330007 0.0000000

Данных очень много, но благодаря уникальным возможностям языка программирования R мы можем легко отсортировать эти данные по заданным условиям. Например выведем только данные по тем группам, которые статистически значимо не различаются. 

a = as.data.frame(ans$sort)
a[a$`p adj` > 0.05,] #стат значимо не отличаются

> a = as.data.frame(ans$sort)
> a[a$`p adj` > 0.05,] #стат значимо не отличаются
 diff lwr upr p adj
sort2-sort1 -0.25616667 -1.2839968 0.77166345 0.99029723
sort5-sort1 0.13233333 -0.8291137 1.09378037 0.99965082
sort6-sort1 -0.44866667 -1.4764968 0.57916345 0.85675954
sort5-sort2 0.38850000 -0.7016785 1.47867846 0.94131285
sort6-sort2 -0.19250000 -1.3416490 0.95664900 0.99892139
sort4-sort3 -0.89195804 -2.0451180 0.26120196 0.25210029
sort7-sort3 -0.03494505 -1.1191170 1.04922687 0.99999994
sort5-sort4 -1.08793939 -2.2053085 0.02942974 0.06221455
sort7-sort4 0.85701299 -0.2771138 1.99113979 0.27891662
sort6-sort5 -0.58100000 -1.6711785 0.50917846 0.69870571

Как видим, все теперь наглядно видно и например sort7-sort3 практически не отличаются p adj = 0.99999994. Вспомним что эти данные были сгенерированы с заданными усчловиями искусственно (среднее арифметическое у них : 13.4 и 13.5 соответсвенно)

sort3 = round(rnorm(130, 13.4, 2.5), 1)

sort7 = round(rnorm(140, 13.5, 4.4), 1)

Выведем теперь данные по всем группам, которые имеют статистически значимые различия:

a[a$`p adj` < 0.05,] # есть различия 

> a[a$`p adj` < 0.05,] # есть различия 
 diff lwr upr p adj
sort3-sort1 2.112231 1.1094124 3.1150491 1.521462e-08
sort4-sort1 1.220273 0.1636463 2.2768992 1.190434e-02
sort7-sort1 2.077286 1.0964135 3.0581579 1.234922e-08
sort3-sort2 2.368397 1.2415641 3.4952307 1.649781e-08
sort4-sort2 1.476439 0.3014636 2.6514152 4.065762e-03
sort7-sort2 2.333452 1.2261047 3.4408001 1.495517e-08
sort5-sort3 -1.979897 -3.0465272 -0.9132677 1.106210e-06
sort6-sort3 -2.560897 -3.6877307 -1.4340641 6.748296e-10
sort6-sort4 -1.668939 -2.8439152 -0.4939636 5.869143e-04
sort7-sort5 1.944952 0.8989292 2.9909756 1.051076e-06
sort7-sort6 2.525952 1.4186047 3.6333001 5.730612e-10

Данные можно так же сортировать по заданным условиям, например отберем только те которые p adj будет отличаться больше 1.e-06

a[a$`p adj`<= 1e-07,]

> a[a$`p adj`<= 1e-07,]
 diff lwr upr p adj
sort3-sort1 2.112231 1.109412 3.115049 1.521462e-08
sort7-sort1 2.077286 1.096414 3.058158 1.234922e-08
sort3-sort2 2.368397 1.241564 3.495231 1.649781e-08
sort7-sort2 2.333452 1.226105 3.440800 1.495517e-08
sort6-sort3 -2.560897 -3.687731 -1.434064 6.748296e-10
sort7-sort6 2.525952 1.418605 3.633300 5.730612e-10

А теперь давайте выясним, какие группы максимально различаются друг от друга:

a[a$`p adj` == min(a$`p adj`),] # max различаются

> a[a$`p adj` == min(a$`p adj`),] # max различаются
 diff lwr upr p adj
sort7-sort6 2.525952 1.418605 3.6333 5.730612e-10

Получили ответ: sort7-sort6 и это действительно так, как их средние значения при генерации максимально различались от остальных групп

sort6 = round(rnorm(120, 11.1, 2.8), 1)
sort7 = round(rnorm(140, 13.5, 4.4), 1)

Полный скрипт ниже:

# Дисперсионный анализ трех групп
set.seed(5454)
sort1 = round(rnorm(100, 11.6, 3), 1)
sort2 = round(rnorm(120, 11.4, 3.3), 1)
sort3 = round(rnorm(130, 13.4, 2.5), 1)
sort4 = round(rnorm(110, 12.8, 2.4), 1)
sort5 = round(rnorm(150, 11.5, 2.4), 1)
sort6 = round(rnorm(120, 11.1, 2.8), 1)
sort7 = round(rnorm(140, 13.5, 4.4), 1)

df=rbind(

data.frame(sort='sort1', massa = sort1),
data.frame(sort='sort2', massa = sort2),
data.frame(sort='sort3', massa = sort3),
data.frame(sort='sort4', massa = sort4),
data.frame(sort='sort5', massa = sort5),
data.frame(sort='sort6', massa = sort6),
data.frame(sort='sort7', massa = sort7))

head(df)  
boxplot(massa ~ sort, df)
grid(col='black')
boxplot(massa ~ sort,df,add=T)       

tmassa = aov(massa ~ sort, df)
summary(tmassa)
ans=TukeyHSD(tmassa)
ans
a = as.data.frame(ans$sort)
a[a$`p adj` > 0.05,] #стат значимо не отличаются
a[a$`p adj` < 0.05,] # есть различия 
a[a$`p adj` == min(a$`p adj`),] # max различаются
a[a$`p adj`<= 1e-07,]
a[a$`p adj` < 0.05,][4,]
a[a$`p adj` == min(a$`p adj`),]

library(ggplot2)
ggplot(df, aes(massa, sort))+
  stat_summary(fun.data = mean_cl_boot, geom = "errorbar", width = 0.1, size = 1)+
  stat_summary(fun.y = mean, geom = "point", size = 6, shape = 22, fill = "white")+
  theme_bw()+
  xlab("масса граммы")+
  ylab("сорта")

» Вход на сайт

» Поиск

» Работа с файлами

» Вся графика

» Гистогра́мма

» Теория вероятности

» Сравнение групп

» Дисперс анализ

» Блог

» Календарь
«  Апрель 2026  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
27282930

» Архив записей


Copyright MyCorp © 2026
uCoz