Взвешивание данных таблиц сопреженности в R
30/04/15 21:22 Относится к категории: Анализ данных | R
Пару месяцев назад столкнулся с необходимостью взвешивания данных в R. Для решения этой задачи существует библиотека weights, разработанная доцентом Мичиганского университета Джошем Пасеком. Это расширение, среди прочего, позволяет взвешивать средние значения, одномерные распределения и результаты некоторых статистических тестов. Но в случае необходимости взвешивания таблиц сопряженности эта библиотека мало применима. Единственная возможность - создание новой переменной, категории которой сгенерированы как результат перекрестной классификации категорий переменных, образующих таблицу сопряженности. Например, для переменных пол (две категории) и образование (три категории) необходимо создать новую переменную с шестью категориями и уже к ней применить функцию wpct() библиотеки weights. Способ, по правде сказать, не самый интересный. Других возможностей для взвешивания таблиц сопряженности я не обнаружил. Поэтому решил написать свою функцию. При этом я столкнулся со следующими вопросами: 1) как осуществляется взвешивание данных таблиц сопряженности? 2) как валидизировать функцию? 3) какие средства самого R лучше использовать?
Ответы такие: 1) частоты (не пропорции) каждой ячейки таблицы сопряженности необходимо умножить на средний вес, вычисленный для соответствующих категорий переменных (например, средний вес для мужчин со средним специальным образованием), а полученный результат округлить до целых значений; 2) результаты своих взвешиваний я сравнивал с результатами анализа в SPSS; 3) необходимо создать вектор средних весов и умножить на них частотную таблицу сопряженности, а полученный результат округлить до целых значений. По последнему пункту необходимо уточнить. Дело в том, что использовать для вычисления средних весов функцию aggregate() не лучшее решение - в результатах не будет никакой информации для тех комбинации категорий, в которых нет наблюдений. Поэтому размерность создаваемого вектора в ряде случаев не будет соответствовать размерности таблицы сопряженности. На самом деле aggregate() использовать не только можно но и нужно. Оптимизированный вариант функции для взвешивания с использованием aggregate() предложил Кирилл Захаров.
Далее в дидактических целях приведены оба варианта функции. В моем варианте функции (forweight_fin()) в качестве первого аргумента используется вектор с весами, в качестве второго - вектор для первой переменной, в качестве третьей - вектор для второй переменной или любое логическое значение (если это одномерное распределение). В варианте Кирилла необходимо указать вектор с весами, вектор для первой переменной и (если это двумерная таблица сопряженности) вектор для второй переменной.
Далее в дидактических целях приведены оба варианта функции. В моем варианте функции (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