Алгоритм сравнения социально-демографических групп: на примере установок на гражданскую активность

Stacks Image 3
Далее представлен пример визуализации результатов проверки множественных гипотез (тест Вилкоксона) после контроля методом Беньямин-Хохберта.

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

В качестве параметра, подлежащего сравнению, использован индекс построенный на основании следующих индикаторов:
  • Мне все равно какая будет власть, только бы не стало хуже
  • Я свой выбор давно уже сделал, поэтому не хочу принимать
    участие в нынешней политической жизни
  • Какой смысл бороться за свои права, если власть
    своими действиями откровенно их игнорирует

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

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

В этой заметке я сосредоточился на технической реализации, поэтому будет неудивительно, если у Вас возникнут вопросы и критические заменчания.

Анализ данных проведен на массиве данных социологического мониторинга «Украинское общество» 2016 года (Институт социологии НАН Украина).

Для анализа и визуализации использован язык программирования R.

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

US2016$demog <- paste(US2016$r3, US2016$vg, sep = ".")
US2016$demog <- paste(US2016$demog, US2016$V278, sep = ".")
US2016$demog <- paste(US2016$demog, ".", sep = "")
US2016$demog <- as.factor(US2016$demog)
table(US2016$demog)

Упорядочиваем эту переменную в соответствии с медианами и первыми квартилями социально-демографических групп (для лучшего представления с помощью диаграммы размахов, см. рис. выше).

oind <- order(as.numeric(by(US2016$gp1, US2016$demog, median, na.rm = T)),
              as.numeric(by(US2016$gp1, US2016$demog, 
                            function(x)quantile(x, na.rm = T)[2])))    
US2016$demog1 <- ordered(US2016$demog, levels=levels(US2016$demog)[oind])
levels(US2016$demog1)

Осуществляем попарные сравнения всех групп (153 сравнения) с мопощью теста Вилкоксона и записываем их в вектор testM. Важно, чтобы вектор был наименованный. Иначе в дальнейшем будет очень сложно понять, какие пары показали статистически значимые различия. Это реализовано с помощью функции paste().

testM <- c()
x <- 1
while(x < 19) {
    for(i in x:18) {
        if(i != x) {
            testM[paste(levels(US2016$demog1)[i], levels(US2016$demog1)[x], sep = " VS ")] <- 
                wilcox.test(US2016$gp1[US2016$demog1 == levels(US2016$demog1)[i]],
                            US2016$gp1[US2016$demog1 == levels(US2016$demog1)[[x]]])$p.value
        }
    }
    x <- x+1
}

Осуществляем контроль множественных проверок с помощью метода Беньямини-Хохберта. При этом устанавливаем допустимую долю ложно отклоненных гипотез на уровне 5%. Записываем в вектор testF результаты, для которых принята альтернативная гипотеза.

testF <- p.adjust(testM, method = "BH")
testF <- testF[testF < 0.05]

Создаем матрицу forPlot 18 на 18, состоящую из 0. Наименуем строки и столбцы согласно 18 соц-дем группам, которые сравнивались. Создаем список labForMatr, элементы которого содержат информацию о группах, для которых была принята альтернативная гипотеза. Используем этот список для внесения в матрицу единиц для тех пар, по которым была принята альтернативная гипотеза.

forPlot <- matrix(0, ncol = 18, nrow = 18)
rownames(forPlot) <- levels(US2016$demog1)
colnames(forPlot) <- levels(US2016$demog1)

labForMatr <- strsplit(labels(testF), " VS ")

for (i in 1:length(labForMatr)) {
    forPlot[labForMatr[[i]][1],labForMatr[[i]][2]] <- 1
    forPlot[labForMatr[[i]][2],labForMatr[[i]][1]] <- 1 
}

Осуществляем на основании финальной матрицы многомерное шкалирование и готовим массив fpts для визуализации.

distanciya <- dist(forPlot)
fit <- cmdscale(distanciya,eig=TRUE, k=2)
fit # view results
fpts <- as.data.frame(fit$points)
fpts$V1 <- fpts$V1 * -1
fpts$V3 <- row.names(forPlot)

Строим диаграмму (см. рис. ниже) на основании результатов многомерного шкалирования, где точки представляют различные соц-дем группы (понадобятся библиотеки ggplot2 и ggrepel). Делим ее на сектора, позволяющие осуществить интерпретацию различий. Одна вертикальная линия проходит через 0 по оси Y и пересекает координату групп, которые вообще не показали статистически значимых отличий с другими. На диаграмме это молодые мужчины на юго-востоке (СМЧ) и молодые мужчины на западе (ЗМЧ). В свою очередь для демонстрации статистически значимых различий использованы стрелки. Если стрелка уходит от определенной координаты к вертикальной линии, то соответствующая демографическая(-ие) группа(-ы) является статистически отличной(-ыми) от всех групп, находящихся слева от этой линии. Если же стрелка идет к горизонтальной линии, то соответствующая демографическая(-ие) группа(-ы) являются статистически отличной(-ыми) от всех групп, находящихся ниже этой линии.

par(mar=c(2.5,7,2,1))

p <- ggplot(data = fpts, aes(x = V1, y = V2, label=V3))


pfin <- p + geom_point(size = 5, colour = "black", alpha = 0.5) + 
    ggtitle("Індекс: індикатори №1,3,4") + xlab("Вісь Х: активність <=> пасивність") + 
    ylab("Вісь Y: більша відмінність <=> менша відмінність")
    
pfin <- pfin + geom_errorbarh(aes(y=-0.25, xmin=-1.4, xmax=0, height = 0)) +
    geom_errorbarh(aes(y=-0.6, xmin=-1.4, xmax=0, height = 0)) +
    geom_vline(aes(xintercept=0)) +
    geom_curve(aes(x = 1.2, y = 0.5, xend = -0.7, yend = -0.6), linetype="twodash", 
               arrow = arrow(length = unit(0.015, "npc"))) +
    geom_curve(aes(x = 1.75, y = 0.21, xend = -0.5, yend = -0.25), linetype="twodash", 
               arrow = arrow(length = unit(0.015, "npc"))) +
    geom_segment(aes(x = 2.56, y = -0.815, xend = 0, yend = -0.815), linetype="twodash", 
                 arrow = arrow(length = unit(0.015, "npc")))
pfin + 
    geom_label_repel(aes(label = V3),
                     box.padding   = 0.1, 
                     point.padding = 0.2,
                     segment.color = 'grey50',
                     size = 4)
Stacks Image 10
Data science (3)
Europe (2)
Geopolitics (2)
Infographics (1)
R (26)
Russia (2)
SPSS (2)
Ukraine (2)
Акционализм (1)
Анализ данных (27)
Аномия (1)
Выборка (1)
Выступления (3)
Геополитика (12)
Гражданское общество (2)
Демократизация (1)
Европа (4)
Интернет ресурсы (1)
Инфографика (8)
Исследовательские дизайны (1)
Историческая социология (10)
История социологии (5)
Киберспорт (1)
Книги (7)
Массивы (3)
Методология социальных исследований (1)
Методология социологических исследований (2)
Научная жизнь (3)
Новости (6)
Обратная связь (1)
Персоналии (3)
Православные конфессии в Украине (1)
Президентская власть (1)
Психологический дистресс (18)
Психология (5)
Публицистика (2)
Революция (1)
Результаты исследований (28)
Религия (3)
Россия (2)
Согласование концептов (4)
Социальная гетерогенность (1)
Социальная работа (1)
Социологическая теория (6)
Социологические тесты (1)
Социологическое образование (5)
Теория конфликта (2)
Теория социального измерения (8)
Украина (9)
Учебные планы (2)
Философия (1)
Шкалирование (36)
Экономика (1)
Эмпирическая социология (46)

free counters
Яндекс.Метрика