Для выполнения работы использовался язык R версии 3.6.3. Необходимые пакеты скачиваются командой
install.packages(c("readxl", "dplyr", "ggplot2", "ggpubr", "corrplot", "psych", "MASS",
"tree", "randomForest", "TeachingDemos", "mice", "corrgram", "magrittr", "plotly",
"factoextra"))
и подключаются
library(readxl) #чтение из excel
library(dplyr) #современные средства программирования, включая функциональное
library(ggplot2) #красивые удобные графики
library(ggpubr) #группировка изображений
library(corrplot) #картинка для корреляционной матрицы
library(psych) #факторный анализ
library(MASS) #линейный дискриминантный анализ
library(tree) #визуализация деревьев
library(randomForest) #случайные леса
library(TeachingDemos) #пиктограммы
library(mice) #обработка отсутствующих значений
library(corrgram) #коррелограммы
library(magrittr) #конвеерный оператор
library(plotly) #интерактивная графика
library(factoextra) #графика по главным компонентам
Также использовался номер варианта
nv = 7 #номер варианта
Дополнительная информация: сайт по статистике в R, огромная статья по построению моделей в R, cтатья по кластерному, факторному и дискриминантному анализу в R, курс по анализу данных в R, курс по основам R как языка программирования, курс по статистике в R, перечень основых функций языка, математические операции в R, книги по R на моём GitHub, набор ссылок, отличный сайт по R.
Подготовим данные:
datacrude = data.frame(read_excel("Таблица 1.xlsx")) #считывание таблицы
data = datacrude[5:nrow(datacrude), -1] #удаление лишних строк и столбцов
data = data[-nv, ] #удаление строки в соответствиии с номером варианта
colnames(data) = c("Country", "Doctors", "Deaths", "GDP", "Costs") #переименование столбцов (для лаконичности)
data[, 1] = factor(data[, 1]) #первая переменная из количественной преобразуется в номенативную
row.names(data) = as.character(1:nrow(data)) #наблюдения нумеруются
data %>% tbl_df() #таблица старого образца переводится в более удобный и выводится
data[, 2:5] = apply(data[, 2:5], 2, function(x) scale(as.numeric(x))) #тут переменные из текста преобразуются в числа и стандартизируются
Полученная таблица (стандартизованные данные):
data %>% tbl_df()
Средние и стандартные отклонения:
means = apply(data[, -1], 1, mean)
sds = apply(data[, -1], 1, sd)
data_frame(countries = data[, 1], means, sds)
Для решения задачи создается матрица (евклидовых) расстояний
(d = dist(data[, 2:5], method = "euclidean")) #матрица расстояний
## 1 2 3 4 5 6 7
## 2 4.4120797
## 3 4.3697012 0.6115859
## 4 1.5382991 3.5610208 3.7186612
## 5 1.7880599 3.5531815 3.7371442 0.4723246
## 6 1.6638732 3.0472614 3.0908033 1.0870717 1.4099074
## 7 1.5250963 3.2594515 3.2699370 1.1240009 1.1617940 0.9488992
## 8 4.6803367 1.6849098 1.9707704 3.7231844 3.5064730 3.6321676 3.4486947
## 9 2.1305565 2.7495920 2.7866134 1.4625949 1.3551118 1.2791960 0.6699219
## 10 4.1441528 0.7076818 0.5346512 3.4849263 3.5594776 2.8188389 3.1403530
## 11 3.2486216 1.8206319 2.1256680 2.1992479 2.3440153 1.7984619 2.3867169
## 12 1.7145100 4.2598610 4.3159864 1.7317365 2.2010009 1.5063236 2.2014486
## 13 3.9266511 0.9626679 1.1543992 3.1534712 3.2038842 2.7121034 3.0370283
## 14 4.4585820 2.0655695 2.3403208 3.4726012 3.1990304 3.4902301 3.1859046
## 15 3.8527282 1.1937521 1.5010755 2.9190773 3.0342823 2.3476421 2.8678297
## 16 4.2780349 1.7992641 1.7544006 3.6966667 3.9110938 2.9014521 3.5410103
## 17 1.1516395 3.7772898 3.8710270 0.4959369 0.6400378 1.2052633 0.9456070
## 18 5.2950469 0.9960504 1.0830876 4.4639940 4.4123030 3.9438542 4.0589639
## 19 2.1800493 3.3145362 3.5576672 0.7224496 0.4269473 1.5073417 1.3700879
## 8 9 10 11 12 13 14
## 2
## 3
## 4
## 5
## 6
## 7
## 8
## 9 2.8106515
## 10 2.2618696 2.7310492
## 11 2.7345527 2.1695599 1.7354273
## 12 4.9733098 2.7118614 3.9329969 2.6691311
## 13 2.0363879 2.6398079 0.8589113 1.3939745 3.7375233
## 14 0.5914261 2.5381635 2.6064969 2.8282744 4.8619004 2.3749627
## 15 2.5278567 2.5431818 1.0871038 0.8260148 3.3153464 1.0481624 2.7533921
## 16 3.4174312 3.3313885 1.2636674 1.7764577 3.5961051 1.5965054 3.7338925
## 17 3.8739706 1.4137608 3.6706682 2.5551808 1.8380458 3.3737126 3.5987458
## 18 1.8095780 3.4938982 1.4651779 2.7833382 5.2109929 1.8695011 2.2686056
## 19 3.2468663 1.3911303 3.3826377 2.1055139 2.3815860 3.0044314 2.9454487
## 15 16 17 18
## 2
## 3
## 4
## 5
## 6
## 7
## 8
## 9
## 10
## 11
## 12
## 13
## 14
## 15
## 16 1.2122349
## 17 3.2265303 3.9414781
## 18 2.0977766 2.4660759 4.6574785
## 19 2.7937204 3.7553911 1.0377559 4.1630214
которая используется функцией кластеризации по методу ближайшего соседа с расстоянием Варда между кластерами:
fit <- hclust(d, method = "ward.D")
Дендрограмма полученной кластеризации:
plot(fit, labels = data$Country, xlab = "Countries")
сумма внутригрупповых расстояний по мере объединения кластеров:
plot(fit$height, xlab = "step", ylab = "dist", type = "b", col = "blue", lwd = 1,
main = "Расстояния при объединении кластеров")
Схема объединения по шагам:
mat = fit$merge
resu = list()
countries = as.character(data$Country)
for (i in 1:nrow(mat)) {
if (mat[i, 1] < 0) {
a = countries[-mat[i, 1]]
} else {
a = as.character(resu[[mat[i, 1]]])
}
if (mat[i, 2] < 0) {
b = countries[-mat[i, 2]]
} else {
b = as.character(resu[[mat[i, 2]]])
}
resu[[i]] = c(a, b)
}
names(resu) = paste("Шаг", 1:nrow(mat), "расстояние", fit$height)
print(resu)
## $`Шаг 1 расстояние 0.426947302377`
## [1] "Армения" "Киргизия"
##
## $`Шаг 2 расстояние 0.495936862326806`
## [1] "Азербайджан" "Казахстан"
##
## $`Шаг 3 расстояние 0.534651158339984`
## [1] "Австрия" "Германия"
##
## $`Шаг 4 расстояние 0.59142613070119`
## [1] "Великобритания" "Ирландия"
##
## $`Шаг 5 расстояние 0.669921900930876`
## [1] "Болгария" "Венгрия"
##
## $`Шаг 6 расстояние 0.701294749091246`
## [1] "Австралия" "Австрия" "Германия"
##
## $`Шаг 7 расстояние 0.826014818116822`
## [1] "Греция" "Испания"
##
## $`Шаг 8 расстояние 0.974841826914247`
## [1] "Армения" "Киргизия" "Азербайджан" "Казахстан"
##
## $`Шаг 9 расстояние 1.17900272101096`
## [1] "Дания" "Австралия" "Австрия" "Германия"
##
## $`Шаг 10 расстояние 1.26208946988791`
## [1] "Беларусь" "Болгария" "Венгрия"
##
## $`Шаг 11 расстояние 1.68253703237057`
## [1] "Канада" "Дания" "Австралия" "Австрия" "Германия"
##
## $`Шаг 12 расстояние 1.71451000628185`
## [1] "Россия" "Грузия"
##
## $`Шаг 13 расстояние 1.71712349824102`
## [1] "Италия" "Греция" "Испания"
##
## $`Шаг 14 расстояние 2.49230286327314`
## [1] "Армения" "Киргизия" "Азербайджан" "Казахстан" "Беларусь"
## [6] "Болгария" "Венгрия"
##
## $`Шаг 15 расстояние 3.16150026414533`
## [1] "Россия" "Грузия" "Армения" "Киргизия" "Азербайджан"
## [6] "Казахстан" "Беларусь" "Болгария" "Венгрия"
##
## $`Шаг 16 расстояние 3.29068732365053`
## [1] "Канада" "Дания" "Австралия" "Австрия" "Германия" "Италия"
## [7] "Греция" "Испания"
##
## $`Шаг 17 расстояние 5.42357100170829`
## [1] "Великобритания" "Ирландия" "Канада" "Дания"
## [5] "Австралия" "Австрия" "Германия" "Италия"
## [9] "Греция" "Испания"
##
## $`Шаг 18 расстояние 19.2875906745862`
## [1] "Россия" "Грузия" "Армения" "Киргизия"
## [5] "Азербайджан" "Казахстан" "Беларусь" "Болгария"
## [9] "Венгрия" "Великобритания" "Ирландия" "Канада"
## [13] "Дания" "Австралия" "Австрия" "Германия"
## [17] "Италия" "Греция" "Испания"
Попробуем узнать, сколько кластеров будет достаточно. Для этого рассчитаем суммы внутригрупповых расстояний, когда число кластеров равно 1, 2, … 8, и изобразим их на графике:
it = 1:8
sums = sapply(it, function(k) kmeans(data[, 2:5], k)$tot.withinss)
plot(it, sums, type = "b", col = "red", main = "Суммы внутригрупповых расстояний при разном числе кластеров")
По принципу метода каменистой осыпи делаем вывод, что исходный набор данных естественно делится на 2 или 3 кластера. Напишем функцию, которая строит модель для заданного числа кластеров, проводит анализ этой модели и строит некоторые графики:
# функция, проводящая некоторый анализ и строящая графики для заданного числа
# кластеров
getimage = function(k) {
fit = kmeans(data[, 2:5], k) #строится модель
cat("Основная информация: \n")
print(fit)
# cat('Внутригрупповые суммы:',fit$withinss,'\n')#внутригрупповые суммы
# cat('Общая сумма:', fit$betweenss,'\n')
cat("Матрица расстояний:\n")
print(dist(fit$centers)) #матрица расстояний
cat("Центры:\n")
print(fit$centers)
# Добавляем кластер к фрейму данных
library(dplyr)
newdata = as_data_frame(data) %>% mutate(cluster = factor(fit$cluster))
# агрегирование данных по группам
means = newdata[, 2:6] %>% group_by(cluster) %>% summarise(meanCosts = mean(Costs),
sdCosts = sd(Costs), meanDoctors = mean(Doctors), sdDoctors = sd(Doctors),
meanGDP = mean(GDP), sdGDP = sd(GDP), meanDeaths = mean(Deaths), sdDeaths = sd(Deaths))
print(means)
means = means[, c(1, 2, 4, 6, 8)] #берётся сабсет только из значений для средних
lbs = c("cluster1", "cluster2", "cluster3", "cluster4", "cluster5")
library(ggplot2)
library(ggpubr)
# здесь создаётся таблица со средними по каждой переменной и каждому классу в том
# виде, в каком удобней рисовать
tmpdata = data.frame(x = 1:4, means = as.numeric(means[1, 2:5]), cluster = rep(lbs[1],
4))
for (i in 2:k) {
tmpdata = rbind(tmpdata, data.frame(x = 1:4, means = as.numeric(means[i,
2:5]), cluster = rep(lbs[i], 4)))
}
tmpdata$cluster = factor(tmpdata$cluster)
ppp = ggplot(tmpdata, aes(x = x, y = means, col = cluster)) + geom_line() + geom_point(size = 4)
pl1 = ggplot(newdata, aes(x = Doctors, y = Deaths, col = cluster)) + geom_point(size = 3) +
theme_bw()
pl2 = ggplot(newdata, aes(x = GDP, y = Costs, col = cluster)) + geom_point(size = 3) +
theme_bw()
pl3 = ggplot(newdata, aes(x = GDP, y = Deaths, col = cluster)) + geom_point(size = 3) +
theme_bw()
pl4 = ggplot(newdata, aes(x = GDP, y = Doctors, col = cluster)) + geom_point(size = 3) +
theme_bw()
costs = ggplot(newdata, aes(x = cluster, y = Costs)) + geom_boxplot() + theme_bw()
deaths = ggplot(newdata, aes(x = cluster, y = Deaths)) + geom_boxplot() + theme_bw()
doctors = ggplot(newdata, aes(x = cluster, y = Doctors)) + geom_boxplot() + theme_bw()
gdp = ggplot(newdata, aes(x = cluster, y = GDP)) + geom_boxplot() + theme_bw()
p1 <- ggarrange(pl1, pl2, pl3, pl4, ncol = 2, nrow = 2)
p2 <- ggarrange(costs, deaths, doctors, gdp, ncol = 2, nrow = 2)
ggarrange(ppp, p1, p2, ncol = 1, nrow = 3, heights = c(1.3, 2, 3))
}
getimage2 = function(k) {
fit = kmeans(data[, 2:5], k) #строится модель
# Добавляем кластер к фрейму данных
library(dplyr)
newdata = as_data_frame(data) %>% mutate(cluster = factor(fit$cluster))
cat("Дисперсионный анализ для каждой переменной,", k, "кластеров \n")
cat("Затраты: \n")
print(summary(aov(Costs ~ cluster, newdata)))
cat("Смерти: \n")
print(summary(aov(Deaths ~ cluster, newdata)))
cat("Врачи: \n")
print(summary(aov(Doctors ~ cluster, newdata)))
cat("ВВП: \n")
print(summary(aov(GDP ~ cluster, newdata)))
# рисуются кластеры через главные компоненты library(cluster)
# print(clusplot(newdata, newdata$cluster, color=TRUE, shade=TRUE, labels=2,
# lines=0))
library(factoextra)
print(fviz_cluster(fit, data[, -1], ellipse.type = "norm"))
}
Используем эту функцию для двух кластеров:
getimage(2)
## Основная информация:
## K-means clustering with 2 clusters of sizes 10, 9
##
## Cluster means:
## Doctors Deaths GDP Costs
## 1 -0.3094347 -0.8535616 0.8736311 0.7776878
## 2 0.3438163 0.9484018 -0.9707013 -0.8640976
##
## Clustering vector:
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
## 2 1 1 2 2 2 2 1 2 1 1 2 1 1 1 1 2 1 2
##
## Within cluster sum of squares by cluster:
## [1] 16.671286 9.045834
## (between_SS / total_SS = 64.3 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
## Матрица расстояний:
## 1
## 2 3.125833
## Центры:
## Doctors Deaths GDP Costs
## 1 -0.3094347 -0.8535616 0.8736311 0.7776878
## 2 0.3438163 0.9484018 -0.9707013 -0.8640976
## # A tibble: 2 x 9
## cluster meanCosts sdCosts meanDoctors sdDoctors meanGDP sdGDP meanDeaths
## <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 0.778 0.596 -0.309 1.12 0.874 0.426 -0.854
## 2 2 -0.864 0.504 0.344 0.766 -0.971 0.177 0.948
## # ... with 1 more variable: sdDeaths <dbl>
Видно, что исходные наблюдения хорошо разделяются на две группы. Если использовать три кластера, такое разделение будет уже сомнительным:
getimage(3)
## Основная информация:
## K-means clustering with 3 clusters of sizes 8, 9, 2
##
## Cluster means:
## Doctors Deaths GDP Costs
## 1 0.1318025 -0.9074724 0.9173579 0.8810550
## 2 0.3438163 0.9484018 -0.9707013 -0.8640976
## 3 -2.0743833 -0.6379186 0.6987241 0.3642190
##
## Clustering vector:
## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
## 2 1 1 2 2 2 2 3 2 1 1 2 1 3 1 1 2 1 2
##
## Within cluster sum of squares by cluster:
## [1] 8.0886580 9.0458341 0.1748924
## (between_SS / total_SS = 76.0 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
## Матрица расстояний:
## 1 2
## 2 3.177978
## 3 2.292343 3.558067
## Центры:
## Doctors Deaths GDP Costs
## 1 0.1318025 -0.9074724 0.9173579 0.8810550
## 2 0.3438163 0.9484018 -0.9707013 -0.8640976
## 3 -2.0743833 -0.6379186 0.6987241 0.3642190
## # A tibble: 3 x 9
## cluster meanCosts sdCosts meanDoctors sdDoctors meanGDP sdGDP meanDeaths
## <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 0.881 0.627 0.132 0.704 0.917 0.457 -0.907
## 2 2 -0.864 0.504 0.344 0.766 -0.971 0.177 0.948
## 3 3 0.364 0.123 -2.07 0.158 0.699 0.315 -0.638
## # ... with 1 more variable: sdDeaths <dbl>
Теперь попробуем визуально оценить качество кластеризации через главные компоненты (дополнительно делается дисперсионный анализ по каждой переменной):
for (i in 2:5) getimage2(i)
## Дисперсионный анализ для каждой переменной, 2 кластеров
## Затраты:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 1 12.768 12.768 41.49 6.09e-06 ***
## Residuals 17 5.232 0.308
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Смерти:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 1 15.381 15.381 99.83 1.57e-08 ***
## Residuals 17 2.619 0.154
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Врачи:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 1 2.021 2.0214 2.151 0.161
## Residuals 17 15.979 0.9399
## ВВП:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 1 16.113 16.113 145.1 9.48e-10 ***
## Residuals 17 1.887 0.111
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Дисперсионный анализ для каждой переменной, 3 кластеров
## Затраты:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 2 13.195 6.598 21.97 2.58e-05 ***
## Residuals 16 4.805 0.300
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Смерти:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 2 15.497 7.749 49.53 1.4e-07 ***
## Residuals 16 2.503 0.156
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Врачи:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 2 9.809 4.904 9.58 0.00184 **
## Residuals 16 8.191 0.512
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## ВВП:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 2 16.189 8.095 71.52 1.05e-08 ***
## Residuals 16 1.811 0.113
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Дисперсионный анализ для каждой переменной, 4 кластеров
## Затраты:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 3 13.453 4.484 14.79 9.42e-05 ***
## Residuals 15 4.547 0.303
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Смерти:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 3 16.103 5.368 42.44 1.45e-07 ***
## Residuals 15 1.897 0.126
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Врачи:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 3 12.831 4.277 12.41 0.000242 ***
## Residuals 15 5.169 0.345
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## ВВП:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 3 16.189 5.396 44.7 1.02e-07 ***
## Residuals 15 1.811 0.121
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Дисперсионный анализ для каждой переменной, 5 кластеров
## Затраты:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 4 15.085 3.771 18.11 2.01e-05 ***
## Residuals 14 2.915 0.208
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Смерти:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 4 16.114 4.029 29.91 1.01e-06 ***
## Residuals 14 1.886 0.135
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Врачи:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 4 14.707 3.677 15.63 4.6e-05 ***
## Residuals 14 3.293 0.235
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## ВВП:
## Df Sum Sq Mean Sq F value Pr(>F)
## cluster 4 16.666 4.166 43.71 9.2e-08 ***
## Residuals 14 1.334 0.095
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Ещё один способ оценивать качество разбиения на группы — лица Чернова. Идея состоит в том, чтобы для каждой группы найти какую-то характеристику каждой переменной (например, среднее), а затем на основе вектора таких характеристик постоить лица каждой группы: чем лица более похожи, тем группы более близки. Сделаем так для двух кластеров:
# функция делает анализ dataset по методу k-means с k кластерами, затем добавляет
# результаты к датасету
getbykmeans = function(dataset, k) {
fit = kmeans(dataset, k) #строится модель
# Добавляем кластер к фрейму данных
library(dplyr)
newdata = as_data_frame(dataset) %>% mutate(cluster = factor(fit$cluster))
}
# функция считает средние и рисует лица
getfaces = function(k) {
# создаем матрицу средних
means = getbykmeans(data[, 2:5], k) %>% group_by(cluster) %>% summarise_all(funs(mean))
library(TeachingDemos)
faces(means[, 2:5]) #рисуем лица
}
getfaces(2)
Видно, что лица сильно различаются. Для трёх кластеров
getfaces(3)
два лица уже похожи. Для четырёх кластеров имеется две пары очень похожих лиц (то есть данные разбиваются на два кластера, а дальнейшее разбиение уже излишнее – происходит поиск различий там, где их нет):
getfaces(4)
Отсюда вывод: достаточно было использовать только два кластера.
Загрузим данные:
datacrude = data.frame(read_excel("Приложение 1.xlsx"))
data = datacrude[, -c(1)]
data = data[, -c(1, 2, 16, 17)]
data %>% tbl_df()
Визуализация корреляционной матрицы заданного набора переменных:
library(corrplot)
(matr = cor(data))
## Y3 X4 X5 X6 X7 X8
## Y3 1.00000000 0.07650448 -0.072024390 -0.19034971 0.11487125 0.41247593
## X4 0.07650448 1.00000000 -0.143222378 -0.05165605 0.02087309 -0.06787551
## X5 -0.07202439 -0.14322238 1.000000000 -0.10105745 0.04470227 -0.04152517
## X6 -0.19034971 -0.05165605 -0.101057451 1.00000000 0.12261894 -0.24074470
## X7 0.11487125 0.02087309 0.044702272 0.12261894 1.00000000 -0.03683463
## X8 0.41247593 -0.06787551 -0.041525168 -0.24074470 -0.03683463 1.00000000
## X9 0.03646200 0.10789499 -0.113522027 0.02500297 -0.05390234 -0.10077063
## X10 0.08137700 -0.18976437 0.070132267 -0.04524674 -0.11608259 -0.15649952
## X11 0.06540456 -0.07079232 0.033116213 0.22954802 0.19025176 -0.01102561
## X12 0.01947580 -0.36101268 0.032584704 -0.00409325 0.09312382 0.14129715
## X13 0.05655101 0.35261229 0.017754637 0.08272441 0.05377388 -0.09511029
## X14 -0.10504111 -0.01039568 -0.090105051 -0.17096373 0.03176305 0.20164538
## X15 -0.19945635 0.21542253 0.008607521 0.28241807 0.04977926 -0.13295559
## X9 X10 X11 X12 X13 X14
## Y3 0.0364619968 0.08137700 0.06540456 0.01947580 0.05655101 -0.1050411148
## X4 0.1078949930 -0.18976437 -0.07079232 -0.36101268 0.35261229 -0.0103956837
## X5 -0.1135220265 0.07013227 0.03311621 0.03258470 0.01775464 -0.0901050514
## X6 0.0250029745 -0.04524674 0.22954802 -0.00409325 0.08272441 -0.1709637327
## X7 -0.0539023369 -0.11608259 0.19025176 0.09312382 0.05377388 0.0317630498
## X8 -0.1007706318 -0.15649952 -0.01102561 0.14129715 -0.09511029 0.2016453817
## X9 1.0000000000 0.30517775 -0.24507910 -0.09717025 -0.06773852 -0.0005369078
## X10 0.3051777477 1.00000000 -0.04511818 -0.14281619 0.05003536 -0.2694843746
## X11 -0.2450790952 -0.04511818 1.00000000 0.31083103 -0.05178378 0.1425891667
## X12 -0.0971702535 -0.14281619 0.31083103 1.00000000 -0.36987532 0.6225406492
## X13 -0.0677385171 0.05003536 -0.05178378 -0.36987532 1.00000000 -0.2539722434
## X14 -0.0005369078 -0.26948437 0.14258917 0.62254065 -0.25397224 1.0000000000
## X15 -0.0159931107 -0.14937007 -0.08199636 -0.28801774 0.07330715 -0.2548124551
## X15
## Y3 -0.199456352
## X4 0.215422531
## X5 0.008607521
## X6 0.282418070
## X7 0.049779257
## X8 -0.132955585
## X9 -0.015993111
## X10 -0.149370073
## X11 -0.081996358
## X12 -0.288017745
## X13 0.073307149
## X14 -0.254812455
## X15 1.000000000
corrplot(matr)
В наборе данных в целом нет значительных корреляций, поэтому сжать его до трёх-четырёх главных компонент без сильной потери информации не получится.
Результаты аналаза методом главных компонент без вращения:
library(psych)
principal(data, nfactors = 10, rotate = "none") #Создание модели
## Principal Components Analysis
## Call: principal(r = data, nfactors = 10, rotate = "none")
## Standardized loadings (pattern matrix) based upon correlation matrix
## PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 h2 u2 com
## Y3 0.14 -0.53 0.41 0.45 0.28 -0.21 0.07 0.11 -0.07 -0.19 0.86 0.1365 4.6
## X4 -0.44 -0.05 0.58 -0.31 0.16 0.35 0.01 0.27 -0.22 -0.07 0.91 0.0928 4.5
## X5 0.02 0.06 -0.21 0.40 -0.59 0.29 0.40 0.39 0.12 -0.16 1.00 0.0047 4.8
## X6 -0.23 0.65 -0.12 0.11 0.37 -0.29 -0.11 0.14 0.37 -0.21 0.94 0.0614 3.8
## X7 0.08 0.32 0.28 0.37 0.31 0.18 0.60 -0.41 -0.01 0.12 0.99 0.0138 4.9
## X8 0.41 -0.44 0.45 0.08 -0.09 -0.41 0.06 0.19 0.27 0.19 0.89 0.1133 5.6
## X9 -0.21 -0.34 -0.36 -0.29 0.56 0.09 0.36 0.26 0.12 -0.12 0.92 0.0784 5.3
## X10 -0.22 -0.38 -0.60 0.37 0.25 0.11 -0.09 0.10 -0.07 0.39 0.94 0.0627 4.4
## X11 0.35 0.46 0.12 0.45 0.25 0.10 -0.28 0.33 -0.32 0.05 0.92 0.0797 6.3
## X12 0.84 0.20 -0.12 -0.04 0.12 0.09 0.03 0.09 0.14 0.05 0.81 0.1866 1.3
## X13 -0.53 -0.03 0.37 0.23 0.01 0.41 -0.27 -0.01 0.46 0.18 0.95 0.0467 5.1
## X14 0.72 0.08 0.12 -0.44 0.10 0.31 0.04 0.12 0.12 0.18 0.90 0.0967 2.6
## X15 -0.49 0.42 0.14 -0.19 -0.11 -0.39 0.31 0.26 -0.10 0.35 0.94 0.0598 6.1
##
## PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10
## SS loadings 2.40 1.71 1.54 1.32 1.18 0.99 0.92 0.73 0.65 0.53
## Proportion Var 0.18 0.13 0.12 0.10 0.09 0.08 0.07 0.06 0.05 0.04
## Cumulative Var 0.18 0.32 0.43 0.54 0.63 0.70 0.77 0.83 0.88 0.92
## Proportion Explained 0.20 0.14 0.13 0.11 0.10 0.08 0.08 0.06 0.05 0.04
## Cumulative Proportion 0.20 0.34 0.47 0.58 0.68 0.76 0.84 0.90 0.96 1.00
##
## Mean item complexity = 4.6
## Test of the hypothesis that 10 components are sufficient.
##
## The root mean square of the residuals (RMSR) is 0.04
## with the empirical chi square 14.34 with prob < NA
##
## Fit based upon off diagonal values = 0.94
Здесь сперва выведена матрица корреляций, затем SS loadings — это собственные значения каждой компоненты, Proportion Var — доля дисперсий, объясняемых каждой компонентой, Cumulative Var — кумулятивная доля (первая компонента объясняет 18%, первые две вместе — 32%, первые три — 43% и т. д.), дальше то же самое, только в пропорции. По принципу Кайзера следует выделить только 5 компонент, хотя, судя по объяснённым дисперсиям, и восьми может быть недостаточно.
Построим диаграмму каменистой осыпи:
fa.parallel(data, fa = "pc", show.legend = T, main = "Диаграмма каменистой осыпи с параллельным анализом")
Здесь, как и ожидалось, не наблюдается резкого убывания собственных значений, поэтому нельзя сказать, сколько конкретно главных компонент следовало бы выделить. Возмём 6 факторов и проведём анализ с вращением осей:
# варимакс с нормализацией
(vm = principal(apply(data, 2, scale), nfactors = 9, rotate = "varimax"))
## Principal Components Analysis
## Call: principal(r = apply(data, 2, scale), nfactors = 9, rotate = "varimax")
## Standardized loadings (pattern matrix) based upon correlation matrix
## RC1 RC6 RC3 RC5 RC2 RC4 RC9 RC7 RC8 h2 u2 com
## Y3 -0.17 0.80 0.04 0.15 -0.22 0.21 0.05 0.18 -0.09 0.83 0.174 1.6
## X4 -0.06 -0.01 0.91 0.04 -0.05 0.02 0.24 0.01 -0.11 0.90 0.098 1.2
## X5 -0.02 -0.04 -0.08 -0.02 -0.06 0.03 0.03 0.03 0.98 0.97 0.031 1.0
## X6 -0.03 -0.17 -0.16 0.07 0.86 0.22 0.18 0.08 -0.14 0.90 0.105 1.5
## X7 0.04 0.02 0.01 -0.05 0.06 0.08 0.03 0.98 0.03 0.97 0.027 1.0
## X8 0.21 0.86 -0.05 -0.17 -0.02 -0.15 -0.04 -0.12 0.03 0.85 0.151 1.3
## X9 0.09 0.00 0.17 0.89 0.11 -0.25 -0.08 0.01 -0.07 0.91 0.092 1.3
## X10 -0.36 -0.07 -0.33 0.66 -0.20 0.18 0.08 -0.13 0.08 0.78 0.217 2.7
## X11 0.16 0.02 0.00 -0.12 0.12 0.92 -0.03 0.08 0.03 0.92 0.083 1.2
## X12 0.77 0.07 -0.33 -0.03 0.00 0.25 -0.19 0.07 0.05 0.81 0.189 1.8
## X13 -0.22 0.00 0.22 -0.04 0.06 -0.04 0.90 0.03 0.05 0.92 0.078 1.3
## X14 0.91 0.00 0.10 -0.04 -0.14 0.02 -0.09 -0.01 -0.05 0.87 0.130 1.1
## X15 -0.33 -0.09 0.42 -0.14 0.62 -0.14 -0.28 0.02 0.15 0.82 0.183 3.4
##
## RC1 RC6 RC3 RC5 RC2 RC4 RC9 RC7 RC8
## SS loadings 1.82 1.43 1.34 1.32 1.27 1.15 1.04 1.04 1.04
## Proportion Var 0.14 0.11 0.10 0.10 0.10 0.09 0.08 0.08 0.08
## Cumulative Var 0.14 0.25 0.35 0.45 0.55 0.64 0.72 0.80 0.88
## Proportion Explained 0.16 0.12 0.12 0.12 0.11 0.10 0.09 0.09 0.09
## Cumulative Proportion 0.16 0.28 0.40 0.52 0.63 0.73 0.82 0.91 1.00
##
## Mean item complexity = 1.6
## Test of the hypothesis that 9 components are sufficient.
##
## The root mean square of the residuals (RMSR) is 0.05
## with the empirical chi square 22.63 with prob < NA
##
## Fit based upon off diagonal values = 0.91
По результатам анализа видно, что первая компонента сильно коррелирует с переменной Х14 (фондовооруженность труда), шестая — с Y3 (рентабельность) и Х8 (премии и вознаграждения на одного работника), третья — с X4 (трудоемкость единицы продукции), пятая — с Х9 (удельный вес потерь от брака), вторая — с Х6 (удельный вес покупных изделий), четвёртая — с Х11 (среднегодовая численность ППП), девятая — с Х13 (среднегодовой фонд заработной платы), седьмая — с Х7 (коэффициент сменности оборудования), восьмая — с Х5 (удельный вес рабочих в составе ППП).
Также можно увидеть матрицу весовых коэффициентов:
round(unclass(vm$weights), 2) #делается округление до второго знака, чтобы не занимала много места
## RC1 RC6 RC3 RC5 RC2 RC4 RC9 RC7 RC8
## Y3 -0.17 0.56 0.06 0.14 -0.07 0.21 -0.04 0.13 -0.05
## X4 0.06 -0.03 0.74 0.09 -0.13 0.20 0.04 -0.05 0.00
## X5 0.06 0.03 0.05 0.07 0.03 0.01 0.06 -0.01 0.97
## X6 0.10 0.06 -0.23 0.12 0.75 0.06 0.27 -0.04 -0.09
## X7 -0.02 -0.04 -0.04 0.00 -0.06 -0.11 -0.02 0.98 -0.01
## X8 0.11 0.66 -0.07 -0.08 0.24 -0.19 0.06 -0.16 0.10
## X9 0.21 0.07 0.18 0.73 0.20 -0.17 -0.06 0.05 0.06
## X10 -0.20 -0.04 -0.19 0.46 -0.15 0.24 0.03 -0.10 0.06
## X11 -0.02 0.00 0.19 0.01 0.01 0.87 -0.10 -0.10 0.04
## X12 0.42 0.03 -0.14 0.07 0.10 0.09 0.02 0.02 0.07
## X13 0.11 0.03 -0.03 -0.03 0.09 -0.09 0.92 -0.02 0.07
## X14 0.57 -0.06 0.17 0.07 -0.02 -0.06 0.09 -0.04 0.03
## X15 -0.16 0.08 0.32 -0.06 0.46 -0.06 -0.41 -0.03 0.20
а корреляционная матрица для главных компонент показывает их ортогональность:
cor(vm$scores)
## RC1 RC6 RC3 RC5 RC2
## RC1 1.000000e+00 -3.322039e-16 -4.017081e-16 -3.311111e-16 -1.097364e-15
## RC6 -3.322039e-16 1.000000e+00 -2.487410e-18 1.359047e-16 -1.150972e-15
## RC3 -4.017081e-16 -2.487410e-18 1.000000e+00 1.002791e-15 3.791133e-16
## RC5 -3.311111e-16 1.359047e-16 1.002791e-15 1.000000e+00 9.920320e-16
## RC2 -1.097364e-15 -1.150972e-15 3.791133e-16 9.920320e-16 1.000000e+00
## RC4 5.985266e-17 -1.692169e-16 -7.181786e-16 -4.718224e-16 -5.426067e-17
## RC9 -4.962092e-17 -6.727412e-16 -9.481877e-16 -8.728078e-16 -1.537039e-15
## RC7 -3.786863e-17 1.421368e-16 -1.223310e-15 2.718788e-16 1.030068e-15
## RC8 -9.141297e-16 -2.122034e-16 5.827222e-17 -7.918898e-16 -1.165864e-15
## RC4 RC9 RC7 RC8
## RC1 5.985266e-17 -4.962092e-17 -3.786863e-17 -9.141297e-16
## RC6 -1.692169e-16 -6.727412e-16 1.421368e-16 -2.122034e-16
## RC3 -7.181786e-16 -9.481877e-16 -1.223310e-15 5.827222e-17
## RC5 -4.718224e-16 -8.728078e-16 2.718788e-16 -7.918898e-16
## RC2 -5.426067e-17 -1.537039e-15 1.030068e-15 -1.165864e-15
## RC4 1.000000e+00 -4.851502e-16 -6.944523e-16 1.718727e-15
## RC9 -4.851502e-16 1.000000e+00 -9.417104e-16 1.491393e-16
## RC7 -6.944523e-16 -9.417104e-16 1.000000e+00 -8.266536e-16
## RC8 1.718727e-15 1.491393e-16 -8.266536e-16 1.000000e+00
Загрузим данные:
data = data.frame(read_excel("Приложение 2.xlsx"))
data$CLASS = factor(data$CLASS)
data %>% tbl_df()
Визуализация:
pairs(data[, 1:7], col = data$CLASS, pch = 16)
Напишем несколько вспомогательных функций:
library(MASS)
# лица Чернова
showfaces = function() {
newdata = as_data_frame(data) %>% group_by(CLASS) %>% summarise_all(funs(mean))
print(faces(newdata[, 2:8])) #рисуем лица
}
# визуализация кластеров через главные компоненты
showimage = function() {
library(factoextra)
print(fviz_cluster(list(data = data[, 1:7], cluster = data[, 8]), ellipse.type = "norm"))
}
# матрицы, обратные матрицам ковариации для каждого класса
covinv = function(df) {
res = list()
for (i in 1:length(levels(df$CLASS))) res[[i]] = tryCatch({
df[df$CLASS == i, 1:7] %>% as.matrix() %>% cov() %>% solve
}, error = function(r) NA)
# res[[i]]=df[df$CLASS==i,1:7] %>% as.matrix() %>% cov() %>% solve
res
}
# расстояния Махаланобиса от элемента до каждого из классов
distance = function(means, covs, elem) {
res = c()
for (i in 1:nrow(means)) {
vec = (means[i, ] - elem)
res[i] = (vec %*% covs[[i]]) %*% vec
}
return(sqrt(res))
}
# поиск номера элемента в датафрейме
find.number = function(df, elem) {
sm = 0
i = 0
len = length(elem)
while (sm != len) {
i = i + 1
v = ifelse(df[i, ] == elem, T, F)
sm = sum(v)
}
return(i)
}
Лица Чернова показывают, что в двух случаях между парами групп сильной разницы нет:
showfaces()
Проведём обучение через линейный дискриминантный анализ:
ldadat <- lda(CLASS ~ ., data, method = "moment")
Результаты обучения:
# Функция вывода результатов классификации
Out_CTab <- function(model, group) {
cat("Таблица неточностей \"Факт/Прогноз\" по обучающей выборке: \n")
classified <- predict(model)$class
t1 <- table(group, classified)
print(t1)
# Точность классификации и расстояние Махалонобиса
Err_S <- mean(group != classified)
mahDist <- dist(model$means %*% model$scaling)
cat("Точность классификации:", 1 - Err_S[1], "\n")
cat("Расстояния Махалонобиса:\n")
print(mahDist)
# Таблица 'Факт/Прогноз' и ошибка при скользящем контроле
t2 <- table(group, LDA.cv <- update(model, CV = T)$class)
Err_CV <- mean(group != LDA.cv)
cat("Ошибка при скользящем контроле:", Err_CV[1], "\n")
Err_S.MahD <- c(Err_S, mahDist)
Err_CV.N <- c(Err_CV, length(group))
cbind(t1, Err_S.MahD, t2, Err_CV.N)
cat("Результаты многомерного дисперсионного анализа: \n")
ldam <- manova(as.matrix(data[, 1:7]) ~ data$CLASS)
print(summary(ldam, test = "Wilks"))
}
Out_CTab(ldadat, data$CLASS)
## Таблица неточностей "Факт/Прогноз" по обучающей выборке:
## classified
## group 1 2 3 4 5
## 1 9 2 0 0 0
## 2 0 8 2 1 0
## 3 0 2 7 4 0
## 4 0 0 2 15 1
## 5 0 0 0 3 9
## Точность классификации: 0.7384615
## Расстояния Махалонобиса:
## 1 2 3 4
## 2 3.016556
## 3 3.680769 1.726019
## 4 4.766641 2.584622 1.213160
## 5 6.461644 4.081787 2.854497 1.855913
## Ошибка при скользящем контроле: 0.4615385
## Результаты многомерного дисперсионного анализа:
## Df Wilks approx F num Df den Df Pr(>F)
## data$CLASS 4 0.12674 5.4173 28 196.12 2.994e-13 ***
## Residuals 60
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Точность классификации достаточно низкая (74%), вдобавок лямбда Уилкса (0.126) сильно отличается от нуля. Откорректируем классификацию, чтобы добиться стопроцентной точности:
acc = 0 #точность
repeat {
showimage()
ldadat <- lda(CLASS ~ ., data, method = "moment")
means = ldadat$means
cov.mat = covinv(data)
# для всех неправильно найденных найти расстояния до кластеров, отнесённых
# экспертами
prclass = predict(ldadat, data[, 1:7])$class
st = data[data$CLASS != prclass, ]
acc = 1 - nrow(st)/nrow(data)
cat("Точность классификации:", acc, "\n")
if (near(acc, 1))
break
if (nrow(st) == 1) {
number.of.max.distance = 1
} else {
distances = c()
for (i in 1:nrow(st)) {
cls = as.numeric(st[i, 8])
vec = (means[cls, ] - as.numeric(st[i, 1:7]))
if (is.na(cov.mat[[cls]])) {
distances[i] = NA
} else {
distances[i] = (vec %*% cov.mat[[cls]]) %*% vec
}
}
distances = sqrt(distances)
# номер элемента (в таблице неверно отнесённых) с максимальным расстоянием для
# своего кластера
number.of.max.distance = which.max(distances)
}
tt = st[number.of.max.distance, ] #сам элемент
cat("Неправильно отнесённый элемент с максимальным расстоянием (", max(distances,
na.rm = T), ")\n")
# номер того же элемента, но в исходном фрейме
number.of.max.distance.new = find.number(data, tt)
print(data[number.of.max.distance.new, ])
# сделать замену на кластер с минимальным расстоянием
data[number.of.max.distance.new, 8] = predict(ldadat, tt[, 1:7])$class #levels(data$CLASS)[which.min(distance(ldadat$means,cov.mat,as.numeric(tt[,-8])))]
cat("Заменяется на\n")
print(data[number.of.max.distance.new, ])
}
## Точность классификации: 0.7384615
## Неправильно отнесённый элемент с максимальным расстоянием ( 3.93429 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 53 -934 6322 510 548 41 14.7 1187 4
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 53 -934 6322 510 548 41 14.7 1187 3
## Точность классификации: 0.7846154
## Неправильно отнесённый элемент с максимальным расстоянием ( 3.016765 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 54 -161.6 3196 288 149 55 7.6 684 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 54 -161.6 3196 288 149 55 7.6 684 4
## Точность классификации: 0.7846154
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.970361 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 56 -879 3058 169 86 23 5.6 307 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 56 -879 3058 169 86 23 5.6 307 4
## Точность классификации: 0.8
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.904711 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 28 -205 5357 583 716 87 14.8 1606.6 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 28 -205 5357 583 716 87 14.8 1606.6 2
## Точность классификации: 0.8153846
## Неправильно отнесённый элемент с максимальным расстоянием ( 3.172017 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 51 -500 6368 288 169 27 13.3 601 4
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 51 -500 6368 288 169 27 13.3 601 3
## Точность классификации: 0.8153846
## Неправильно отнесённый элемент с максимальным расстоянием ( 3.208787 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 47 -728.3 5448 348 215 28 5.7 367 4
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 47 -728.3 5448 348 215 28 5.7 367 3
## Точность классификации: 0.8153846
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.955268 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 16 -380 5564 565 400 48 14.9 1517 2
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 16 -380 5564 565 400 48 14.9 1517 3
## Точность классификации: 0.8461538
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.838619 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 32 -314 4394 471 396 68 9.9 1065 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 32 -314 4394 471 396 68 9.9 1065 2
## Точность классификации: 0.8461538
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.488618 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 18 -666.8 3988 364 213 35 10.3 943 2
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 18 -666.8 3988 364 213 35 10.3 943 4
## Точность классификации: 0.8615385
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.434652 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 58 -310.7 4166 207 183 32 9.8 487 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 58 -310.7 4166 207 183 32 9.8 487 4
## Точность классификации: 0.8769231
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.629277 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 55 -4 3666 168 131 19 8.3 382 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 55 -4 3666 168 131 19 8.3 382 4
## Точность классификации: 0.8769231
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.474874 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 59 -437 5168 151 96 8 10.7 359 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 59 -437 5168 151 96 8 10.7 359 4
## Точность классификации: 0.8923077
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.333742 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 33 -27 3312 284 229 39 11.1 948 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 33 -27 3312 284 229 39 11.1 948 4
## Точность классификации: 0.8923077
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.664493 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 35 -842 4247 233 189 28 12.8 757 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 35 -842 4247 233 189 28 12.8 757 4
## Точность классификации: 0.9076923
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.489248 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 30 -205 4924 284 292 35 17.5 1010 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 30 -205 4924 284 292 35 17.5 1010 4
## Точность классификации: 0.9076923
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.894696 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 27 -514 5340 364 411 17 14.4 984 3
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 27 -514 5340 364 411 17 14.4 984 4
## Точность классификации: 0.9230769
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.275641 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 7 191 5367 786 819 104 13.7 2011 1
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 7 191 5367 786 819 104 13.7 2011 2
## Точность классификации: 0.9384615
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.203112 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 8 0 6342 486 261 52 24.1 1841 1
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 8 0 6342 486 261 52 24.1 1841 2
## Точность классификации: 0.9384615
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.607064 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 9 -107 5868 531 450 63 22.3 1608 1
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 9 -107 5868 531 450 63 22.3 1608 2
## Точность классификации: 0.9538462
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.474874 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 10 -903 6330 636 401 69 17.6 1768 1
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 10 -903 6330 636 401 69 17.6 1768 2
## Точность классификации: 0.9692308
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.046161 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 20 -94 3900 420 359 53 9.6 1034 2
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 20 -94 3900 420 359 53 9.6 1034 4
## Точность классификации: 0.9846154
## Неправильно отнесённый элемент с максимальным расстоянием ( 2.046161 )
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 61 -855 3483 109 90 16 7.6 237 5
## Заменяется на
## X1 X2 X3 X4 X5 X6 X7 CLASS
## 61 -855 3483 109 90 16 7.6 237 4
## Точность классификации: 1
Результаты для полученной модели:
Out_CTab(ldadat, data$CLASS)
## Таблица неточностей "Факт/Прогноз" по обучающей выборке:
## classified
## group 1 2 3 4 5
## 1 7 0 0 0 0
## 2 0 14 0 0 0
## 3 0 0 11 0 0
## 4 0 0 0 27 0
## 5 0 0 0 0 6
## Точность классификации: 1
## Расстояния Махалонобиса:
## 1 2 3 4
## 2 5.759607
## 3 6.472220 3.248266
## 4 9.288359 4.618247 3.208171
## 5 12.795436 8.147295 6.595490 3.709843
## Ошибка при скользящем контроле: 0.1384615
## Результаты многомерного дисперсионного анализа:
## Df Wilks approx F num Df den Df Pr(>F)
## data$CLASS 4 0.028593 11.768 28 196.12 < 2.2e-16 ***
## Residuals 60
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("Групповые средние:\n")
## Групповые средние:
ldadat$means
## X1 X2 X3 X4 X5 X6 X7
## 1 196.5429 9328.286 898.42857 733.4286 64.28571 26.228571 2547.8571
## 2 -192.2286 5567.000 521.35714 452.2143 75.00000 15.278571 1384.9000
## 3 -282.0909 5587.273 364.06364 276.5455 33.46364 12.709091 807.7273
## 4 -490.5296 3906.000 241.04815 195.7037 29.53333 10.362963 641.8630
## 5 -609.3667 2318.500 79.66667 55.2000 9.70000 3.283333 163.9333
cat("Матрица дискриминантных функций:\n")
## Матрица дискриминантных функций:
ldadat$scaling
## LD1 LD2 LD3 LD4
## X1 6.998429e-04 0.0001441873 -0.0001311974 0.0006733219
## X2 4.517007e-05 0.0001983877 0.0003278794 0.0011001502
## X3 2.380552e-02 0.0120910472 -0.0190093691 -0.0105312748
## X4 -1.112724e-03 0.0005167446 0.0069277131 0.0008733516
## X5 1.961759e-02 -0.0737548966 -0.0115067161 0.0135728516
## X6 3.719980e-01 0.0382745899 -0.1952122703 -0.4280703443
## X7 -6.905738e-03 -0.0033063245 0.0058332004 0.0034695279
plot(ldadat)
rf = lda(CLASS ~ ., data, method = "moment") #фиксируется модель для следующего задания
Исправленная модель:
data %>% tbl_df()
Ошибка нулевая, все данные отнесены правильно. Правило, по которому наблюдение относится в ту или иную группу примерно сделующее (если попробовать иерархический анализ):
library(tree)
datatree <- tree(data[, 8] ~ ., data[, -8])
plot(datatree)
text(datatree)
Считаем тестовые данные и проведём их классификацию по уже построенной модели:
data2 = data.frame(read_excel("Приложение 3.xlsx"))
data2 = apply(data2, 2, as.numeric) %>% as_data_frame()
data2 = data2[31:80, ]
cluster = predict(rf, data2)$class
data2 = data.frame(cbind(data2, cluster))
data2$cluster = factor(data2$cluster)
data2 %>% tbl_df()
Построим диаграммы ядерной плотности для распределения каждой переменной X1-X7 по отнесенным группам, чтобы убедиться в правильности классификации:
library(ggplot2)
library(ggpubr)
ggarrange(ggplot(data2, aes(x = X1, fill = cluster)) + geom_density(alpha = 0.6),
ggplot(data2, aes(x = X2, fill = cluster)) + geom_density(alpha = 0.6), ggplot(data2,
aes(x = X3, fill = cluster)) + geom_density(alpha = 0.6), ggplot(data2, aes(x = X4,
fill = cluster)) + geom_density(alpha = 0.6), ggplot(data2, aes(x = X5, fill = cluster)) +
geom_density(alpha = 0.6), ggplot(data2, aes(x = X6, fill = cluster)) + geom_density(alpha = 0.6),
ggplot(data2, aes(x = X7, fill = cluster)) + geom_density(alpha = 0.6), ncol = 2,
nrow = 4)
Другой вариант — ящики с усами:
ggarrange(ggplot(data2, aes(x = cluster, y = X1)) + geom_boxplot(), ggplot(data2,
aes(x = cluster, y = X2)) + geom_boxplot(), ggplot(data2, aes(x = cluster, y = X3)) +
geom_boxplot(), ggplot(data2, aes(x = cluster, y = X4)) + geom_boxplot(), ggplot(data2,
aes(x = cluster, y = X5)) + geom_boxplot(), ggplot(data2, aes(x = cluster, y = X6)) +
geom_boxplot(), ggplot(data2, aes(x = cluster, y = X7)) + geom_boxplot(), ncol = 2,
nrow = 4)
Также лица Чернова:
newdata = as_data_frame(data2) %>% group_by(cluster) %>% summarise_all(funs(mean))
faces(newdata[, 2:8]) #рисуем лица
Визуализация через главные компоненты:
print(fviz_cluster(list(data = data2[, 1:7], cluster = data2[, 8]), ellipse.type = "norm"))
В целом качество такое же, как в обучающей выборке.
Используются две переменные:
p1 = nchar("Дмитрий") #число букв в имени
p2 = nchar("Пасько") #число букв в фамилии
Прочитаем и обработаем данные:
library(readxl)
library(dplyr)
tab = data.frame(t(read_xlsx("Рожь18век.xlsx")))
names(tab) = sapply(tab[1, ], as.character) #поставить правильные названия
tab = tab[-1, ] #удалить строку с именами
tab = data.frame(Year = sapply(rownames(tab), as.numeric), tab)
tab = sapply(tab, as.numeric) #факторы перевести в числа
tab %>% tbl_df()
Создадим фрейм со средними по годам для всей страны и её районов:
tmptab = tab[, -1]
means = list(rowMeans(tmptab, na.rm = T))
for (i in 1:((ncol(tab) - 1)/2)) {
means[[i + 1]] = rowMeans(tmptab[, c(i, i + 1)], na.rm = T)
}
means = sapply(means, function(col) sapply(col, function(row) ifelse(is.nan(row),
NA, row))) #Заменить все NaN на NA
means = data.frame(tab[, 1], means)
names(means) = c("Year", "Country", "Distrinct1", "Distrinct2", "Distrinct3", "Distrinct4",
"Distrinct5", "Distrinct6", "Distrinct7", "Distrinct8", "Distrinct9")
means %>% tbl_df()
Визуализация полученных значений показывает, что в целом цена ведёт себя одинаково по всем регионам:
library(ggplot2)
g1 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Country), size = 1)
g2 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct1), size = 1, col = 2)
g3 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct2), size = 1, col = 3)
g4 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct3), size = 1, col = 4)
g5 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct4), size = 1, col = 5)
g6 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct5), size = 1, col = 6)
g7 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct6), size = 1, col = 7)
g8 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct7), size = 1, col = "chartreuse2")
g9 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct8), size = 1, col = "chocolate1")
g10 = ggplot(means, aes(x = Year)) + geom_line(aes(y = Distrinct9), size = 1, col = "plum2")
library(ggpubr)
ggarrange(g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, nrow = 5, ncol = 2)
Зададим новый временной ряд:
price1 = c(40 + p1, 43 + p1, 40, 80, 74, 40 + p2, 55 + p2, 42 + p2, 42, 50, 40 +
p2, 43, 43, 35 + p1, 40 + p1, 30, 36 + p1, 50, 30 + p1, 29, 45 + p1, 40, 42,
40, 36, 50, 30 + p1, 24 + p2, 25 + p2, 40, 32 + p1, 30, 20, 30, 25, 32 + p2)
cat("Длина вектора:", length(price1), "\n")
## Длина вектора: 36
summary(price1) #минимальные характеристики
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 20.00 36.75 42.00 42.44 47.25 80.00
Тест Стьюдента для среднего значения (42.4444444) показывает значимое отличие среднего ряда от нуля (p-value очень близкое к нулю):
(ts = t.test(price1, conf.level = 0.95)) #тест Стьюдента для среднего
##
## One Sample t-test
##
## data: price1
## t = 21.17, df = 35, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## 38.37422 46.51467
## sample estimates:
## mean of x
## 42.44444
cat("Доверительный интервал: ", ts$conf.int, "\n")
## Доверительный интервал: 38.37422 46.51467
cat("Стандартная ошибка среднего: ", ts$stderr, "\n")
## Стандартная ошибка среднего: 2.004932
а низкий коэффициент вариации говорит об однородности выборки
vart = sd(price1)/mean(price1) * 100
cat("Коэффициент вариации равен", vart, "%\n")
## Коэффициент вариации равен 28.34197 %
# так как коэффициент вариации < 30%, выборка достаточно однородная
Замечание: в проведённом тесте Стьюдента число степеней свободы было на 1 (а не на 2) меньше числа наблюдений, так как при тесте использовалась одна выборка. Можно считать, что исходная выборка сравнивается с выборкой из единственного элемента 0, поэтому число степеней свободы всего на 1 меньше числа наблюдений. Так же определяется число степеней свободы, например, здесь.
Создадим и визуализируем временной ряд:
library(ggplot2)
yt = c(1133 + p1, 1222, 1354 + p1, 1389, 1342 + p2, 1377, 1491, 1684 + p2)
data = data.frame(time = 1:length(yt), values = yt)
plot(data, type = "b")
В целом, здесь наблюдается линейная составляющая. Построим линейную модель и регрессионную прямую:
fit = lm(values ~ time, data) #создание модели
ggplot(data, aes(x = time, y = values)) + geom_point() + geom_smooth(method = lm)
Посмотрим информацию о модели:
summary(fit) #информация о модели
##
## Call:
## lm(formula = values ~ time, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -93.14 -45.86 -10.46 51.20 96.00
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1098.57 56.30 19.513 1.17e-06 ***
## time 61.93 11.15 5.555 0.00144 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 72.25 on 6 degrees of freedom
## Multiple R-squared: 0.8372, Adjusted R-squared: 0.8101
## F-statistic: 30.85 on 1 and 6 DF, p-value: 0.00144
confint(fit, level = 0.95) #доверительные интервалы
## 2.5 % 97.5 %
## (Intercept) 960.81185 1236.33101
## time 34.64811 89.20903
Самое важное здесь — модель описывает более 80% дисперсий (Adjusted R-squared), каждый её коэффициент (Pr(>|t|)) и она сама (p-value в самом низу, в строке с F-statistic) статистически значимы (поскольку p-value меньше 0.05). Estimate — это коэффициенты модели, значит сама регресионная прямая имеет вид \[y=1098.57 + 61.93 t\]
Коэффициент при \(t\) показывает, на сколько в среднем увеличится \(y\) при изменении \(t\) на единицу. Дисперсионный анализ можно выполнить и отдельно с тем же результатом:
anova(fit)
Теперь выполним прогноз для среднего и индивидульного значений при \(t=9\):
# прогноз среднего
predict(fit, data.frame(time = c(9)), se.fit = TRUE, interval = "confidence", level = 0.95)$fit
## fit lwr upr
## 1 1655.929 1518.169 1793.688
# прогноз индивидуального
predict(fit, data.frame(time = c(9)), se.fit = TRUE, interval = "prediction", level = 0.95)$fit
## fit lwr upr
## 1 1655.929 1431.797 1880.06
Здесь первое число — само предсказанное значение, последующие — границы доверительного интервала.Итак, само предсказанное значение равно 1655.929, доверительный интервал для среднего: [1518.169,1793.688], для индивидуального: [1431.797,1880.06].
Считаем набор данных и проведём некоторую обработку:
library(readxl)
data = data.frame(read_xlsx("РожьВсеГода.xlsx"))
data[, -1] = apply(data[, -1], 2, as.numeric) #перевести в числа все строки
y = t(data[, -1]) #транспонирование для удобства
# получить массив лет
ns = rownames(y)
x = sapply(ns, function(s) as.numeric(substr(s, 2, nchar(s))))
library(mice) #обработать пустые значения
imp = mice(y, seed = 11)
y = complete(imp, action = 1)
df = data.frame(x = x, y = y[, 2]) #объединить данные в фрейм
# print(df[sort(sample(1:nrow(df),13)),2,drop=FALSE]) #вывести 13 случайных строк
Получаем:
df %>% tbl_df()
При этом пропущенные значения были обработаны по алгоритму MICE, для дальнейшего исследования был взят второй район. Визуализировав данные по нему
library(ggplot2)
ggplot(df, aes(x = x, y = y)) + geom_line(col = "green") + geom_point(size = 2) +
geom_smooth(method = lm) + geom_smooth(se = F, col = "red")
приходим к выводу, что в целом поведение цен можно описать линейной моделью, однако для обычной линейной модели здесь явно не будет выполняться требование гомоскедастичности. Попробуем разные преобразования данных (качество модели определяется величиной Adjusted R-squared):
summary(lm(y ~ x, df))
##
## Call:
## lm(formula = y ~ x, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -274.50 -52.12 7.23 45.45 349.99
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4754.7565 241.9835 -19.65 <2e-16 ***
## x 2.7809 0.1333 20.87 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 105.9 on 136 degrees of freedom
## Multiple R-squared: 0.762, Adjusted R-squared: 0.7603
## F-statistic: 435.5 on 1 and 136 DF, p-value: < 2.2e-16
summary(lm(sqrt(y) ~ x, df))
##
## Call:
## lm(formula = sqrt(y) ~ x, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -7.370 -1.454 -0.163 1.628 6.901
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.444e+02 6.017e+00 -24.00 <2e-16 ***
## x 8.829e-02 3.314e-03 26.65 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.633 on 136 degrees of freedom
## Multiple R-squared: 0.8392, Adjusted R-squared: 0.8381
## F-statistic: 710 on 1 and 136 DF, p-value: < 2.2e-16
summary(lm(log(y) ~ x, df))
##
## Call:
## lm(formula = log(y) ~ x, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.00146 -0.26602 -0.00776 0.26103 0.87028
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.762e+01 8.398e-01 -20.99 <2e-16 ***
## x 1.264e-02 4.625e-04 27.34 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3675 on 136 degrees of freedom
## Multiple R-squared: 0.8461, Adjusted R-squared: 0.8449
## F-statistic: 747.6 on 1 and 136 DF, p-value: < 2.2e-16
summary(lm(log(y) ~ log(x), df))
##
## Call:
## lm(formula = log(y) ~ log(x), data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.97970 -0.26965 -0.00275 0.25610 0.85541
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -166.5906 6.2023 -26.86 <2e-16 ***
## log(x) 22.9125 0.8266 27.72 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3633 on 136 degrees of freedom
## Multiple R-squared: 0.8496, Adjusted R-squared: 0.8485
## F-statistic: 768.3 on 1 and 136 DF, p-value: < 2.2e-16
Видно, что модель с логарифмами описывает почти 85% дисперсий, поэтому в дальнейшем будем использовать её. Эта модель имеет вид: \[\log y = -166.5906+22.9125 \log x\] а иначе: \[y=e^{-166.5906}x^{22.9125}\]
Построим тот же график:
ggplot(df, aes(x = log(x), y = log(y))) + geom_line(col = "green") + geom_point(size = 2) +
geom_smooth(method = lm) + geom_smooth(se = F, col = "red")
Для остатков полученной модели проведём сглаживание методом k-средних:
mt = lm(log(y) ~ log(x), df)
res = mt$residuals
# скользящее среднее
library(caTools)
k = c(3, 5, 9)
plot(x, res, type = "l", col = "grey")
for (i in 1:length(k)) {
lines(x, runmean(res, k[i]), col = i, lwd = 2)
}
legend("topleft", c(paste("k =", k)), col = 1:length(k), bty = "n", lwd = 2)
Построим график этой модели в исходной системе координат:
ggplot(df, aes(x = x, y = y)) + geom_line(col = "green") + geom_point(size = 2) +
geom_line(aes(x = x, y = exp(-166.5906) * x^22.9125), col = "red", size = 2)
И последнее: визуализируем корреляции между всеми исходными районами за последние 60 лет наблюдений по отрезкам в 20 лет:
nn = 20
for (i in seq(length(x) - 60, length(x) - nn, nn)) {
tmp = i:(i + nn - 1)
cat("Times:", x[tmp], "\n")
data = y[tmp, ]
cormatrix = cor(data)
cat("Матрица корреляций:\n")
print(cormatrix)
lower = abs(cormatrix[lower.tri(cormatrix)])
cat("Статистика по треугольнику корреляционной матрицы \n")
print(summary(lower[lower != 0]))
corrplot(cormatrix)
}
## Times: 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1866 1867 1868 1869 1870
## Матрица корреляций:
## V1 V2 V3 V4 V5 V6
## V1 1.0000000 0.8291448 0.5366430 0.6129233 0.8161189 0.1555005
## V2 0.8291448 1.0000000 0.7717488 0.7558893 0.7731484 0.5312709
## V3 0.5366430 0.7717488 1.0000000 0.5726800 0.6073105 0.7487677
## V4 0.6129233 0.7558893 0.5726800 1.0000000 0.6249769 0.2797815
## V5 0.8161189 0.7731484 0.6073105 0.6249769 1.0000000 0.1852402
## V6 0.1555005 0.5312709 0.7487677 0.2797815 0.1852402 1.0000000
## Статистика по треугольнику корреляционной матрицы
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.1555 0.5340 0.6129 0.5867 0.7638 0.8291
## Times: 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890
## Матрица корреляций:
## V1 V2 V3 V4 V5 V6
## V1 1.0000000 0.7649144 0.3027825 0.8765815 0.4005356 -0.5869152
## V2 0.7649144 1.0000000 0.2207233 0.5826532 0.1561994 -0.6556954
## V3 0.3027825 0.2207233 1.0000000 0.5261564 0.8357040 0.2055036
## V4 0.8765815 0.5826532 0.5261564 1.0000000 0.6427869 -0.3945789
## V5 0.4005356 0.1561994 0.8357040 0.6427869 1.0000000 0.2367902
## V6 -0.5869152 -0.6556954 0.2055036 -0.3945789 0.2367902 1.0000000
## Статистика по треугольнику корреляционной матрицы
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.1562 0.2698 0.5262 0.4926 0.6492 0.8766
## Times: 1891 1892 1893 1894 1895 1896 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915
## Матрица корреляций:
## V1 V2 V3 V4 V5 V6
## V1 1.0000000 0.8424524 0.8816869 0.8683768 0.9197496 -0.1501039
## V2 0.8424524 1.0000000 0.8579754 0.9580594 0.8652964 -0.2309437
## V3 0.8816869 0.8579754 1.0000000 0.8514249 0.8895560 -0.4079528
## V4 0.8683768 0.9580594 0.8514249 1.0000000 0.9179652 -0.2816789
## V5 0.9197496 0.8652964 0.8895560 0.9179652 1.0000000 -0.2186937
## V6 -0.1501039 -0.2309437 -0.4079528 -0.2816789 -0.2186937 1.0000000
## Статистика по треугольнику корреляционной матрицы
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.1501 0.3448 0.8580 0.6761 0.8856 0.9581
Наглядно видно, что ближе к концу наблюдений корреляция между переменными возрастает. Проблемы с шестой переменной связаны с тем, что для неё было очень много пропущенных значений.