Взвешивание данных таблиц сопреженности в R

1371192895
Пару месяцев назад столкнулся с необходимостью взвешивания данных в R. Для решения этой задачи существует библиотека weights, разработанная доцентом Мичиганского университета Джошем Пасеком. Это расширение, среди прочего, позволяет взвешивать средние значения, одномерные распределения и результаты некоторых статистических тестов. Но в случае необходимости взвешивания таблиц сопряженности эта библиотека мало применима. Единственная возможность - создание новой переменной, категории которой сгенерированы как результат перекрестной классификации категорий переменных, образующих таблицу сопряженности. Например, для переменных пол (две категории) и образование (три категории) необходимо создать новую переменную с шестью категориями и уже к ней применить функцию wpct() библиотеки weights. Способ, по правде сказать, не самый интересный. Других возможностей для взвешивания таблиц сопряженности я не обнаружил. Поэтому решил написать свою функцию. При этом я столкнулся со следующими вопросами: 1) как осуществляется взвешивание данных таблиц сопряженности? 2) как валидизировать функцию? 3) какие средства самого R лучше использовать?
Ответы такие: 1) частоты (не пропорции) каждой ячейки таблицы сопряженности необходимо умножить на средний вес, вычисленный для соответствующих категорий переменных (например, средний вес для мужчин со средним специальным образованием), а полученный результат округлить до целых значений; 2) результаты своих взвешиваний я сравнивал с результатами анализа в SPSS; 3) необходимо создать вектор средних весов и умножить на них частотную таблицу сопряженности, а полученный результат округлить до целых значений. По последнему пункту необходимо уточнить. Дело в том, что использовать для вычисления средних весов функцию aggregate() не лучшее решение - в результатах не будет никакой информации для тех комбинации категорий, в которых нет наблюдений. Поэтому размерность создаваемого вектора в ряде случаев не будет соответствовать размерности таблицы сопряженности. На самом деле aggregate() использовать не только можно но и нужно. Оптимизированный вариант функции для взвешивания с использованием aggregate() предложил Кирилл Захаров.
Далее в дидактических целях приведены оба варианта функции. В моем варианте функции (forweight_fin()) в качестве первого аргумента используется вектор с весами, в качестве второго - вектор для первой переменной, в качестве третьей - вектор для второй переменной или любое логическое значение (если это одномерное распределение). В варианте Кирилла необходимо указать вектор с весами, вектор для первой переменной и (если это двумерная таблица сопряженности) вектор для второй переменной.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# мой вариант

forweight1 <- function(wht,yourvar){
    f <- list()
    for (i in 1:length(levels(yourvar))){
        a <- levels(yourvar)[i]
        d <- mean(wht[which(yourvar==a)])
        if (is.nan(d)) d <- 0
        f[[i]] <- d
    }
    return(as.vector(f,mode="numeric"))
}

forweight2 <- function(wht,yourvar_f,yourvar_s){
    step <- 0
    f <- list()
    for (i in 1:length(levels(yourvar_s))){
        for (j in 1:length(levels(yourvar_f))) {
            step <- step+1
            a <- levels(yourvar_s)[i]
            b <- levels(yourvar_f)[j]
            d <- mean(wht[which(yourvar_f==b & yourvar_s==a)])
            if (is.nan(d)) d <- 0
            f[[step]] <- d
        }
    }
    return(as.vector(f,mode="numeric"))
}

forweight_fin <- function(wt,vr1,vr2){
    if (typeof(vr2) == "logical") {
        forweight1(wt,vr1)
    } else {
        forweight2(wt,vr1,vr2)
    }
}

# вариант Кирилла

weightedTable <- function(w, v1, v2=NULL) {
    if (is.null(v2)) {
        wt <- round(table(v1)*aggregate(w,by=list(v1), FUN=mean)$x)
    } else {
        m <- aggregate(w,by=list(v1,v2), FUN=mean)
        wt <- table(v1,v2)
        for (i in 1:nrow(m)) {
            wt[m[i,1],m[i,2]] <- round(wt[m[i,1],m[i,2]]*m$x[i])
        }
    }
    return(wt)
}

статью подготовил кандидат социологических наук Сергей Дембицкий

Вверх
blog comments powered by Disqus