выборки в R.
Нашёл следующее решение.
И такое.
Однако структура смещений, которая есть у меня в выборке относительно ГС (на пикче), гораздо более сложная, чем описано в примере.
По идее, для каждой половозрастной категории нужно рассчитать свой коэф перевзвешивания.
Вот выборка. n=1200
table(dt$sex,dt$age)/12
Менее 18 лет 18-24 25-34 35-44 45-54 55-64 65 и более
Мужской 0.000000 2.833333 6.916667 11.166667 12.666667 6.750000 3.333333
Женский 0.000000 4.833333 5.666667 7.500000 12.000000 17.666667 8.666667
(На компе норм отображается)
Как считаете, нужно делать это сабсетом или есть более элегентные решения?
Нужно ли приводить к ГС сначала более общие категории (напр. пол/возраст, а потом их сочетания)?
Сейчас читаю документацию по survey в поисках ответов и примеры из других источников, но может у кого будут соображения. #перевзвешивание выборки #опросы #социология #survey
Я в свое время выводил через LibreOffice Calc с стат-бюллетенями в руках, поскольку замучался орудлвать survey :)
Есть какой-то набор типичных ремесленных инструментов, которые в вузах дают (и то не всегда), а в интернетах 2-3 источника в ру. Один из знакомых социологов сказал, что такое он считал в бородатые годы по таблице случайных значений. И было это давно. По SPSS материалов много, но он мне слегка не нравится. Комп 2010ого года помирает от него. Давно подбивает создать какую-то методичку для обработки и интерпретации соцданных в табличных процессорах и R. Тщательно веду конспект для потомков. С полстерскими опросами до того не работал, все исследования, которые проводил, по задумке дизигна не должны были перевзвешиваться. А ведь эти массовые опросы - значимая часть коммерческой "социологии", надо уметь. Почему так мало литературы по теме на R - это вопрос. Может плохо искал. Надо ВЦИОМовские источники раскурить. Там же автор одного из решений советовал книгу: "Complex Surveys: a guide to analysis using R" Думаю над модификацией этого решения: install.packages('survey') install.packages('plyr') # подключим библиотеку library(survey) library(plyr) # здесь некоторые полезные функции require(plyr) # создадим массив данных из 200 наблюдений x <- data.frame( id = 1:200, sex = sample(1:2, 200, T), response = sample(1:5, 200, T) ) # таблица распределения по полу tbl <- count(x, "sex") # добавим переменную freq, в которой находятся веса для коррекции распределения по полу tbl <- transform(tbl, freq = 100/freq) # присоединим весовую переменную к массиву x <- merge(x, tbl) # создадим объект mydesign, в котором хранится информация о взвешенном массиве mydesign <- svydesign(id = ~id, data = x , weights = ~freq)
Модификацией в какую сторону?
Если по каждому сочетанию категорий есть данные ГС, то это постстартификация https://r-survey.r-forge.r-project.org/survey/html/postStratify.html Если данные только по общим категориям (по сочетаниям нет данных), то для пересчёта весов используется рэкинг Там же в syrvey https://r-survey.r-forge.r-project.org/survey/html/rake.html
Ход развития мысли такой, поправьте, пожалуйста, если не прав. есть три dataframe: непосредственно данные опроса, и два df (категории ГС и категории выборки). 1. нужна вторая функция - калибровочная. 2. Делю столбец с относительной частотой признаков в категориях ГС на столбец категорий выборки. a <- sexageN$Freq/sexage$Freq Получается "a" вектор весов. В примере автора функции вроде приведён именованный вектор весов. Пример сложен для моего понимания, потому что мало работал с листами/списками. Основной вопрос - где в функции задаётся условие. Например, если age=18-24 и sex=male то присвоить наблюдению вес такой-то. Понимаю, что там есть всё в описании, но уже полдня сижу голову ломаю, как на мои данные проецировать. Можно, конечно, просто сделать сабсеты и вручную повыкидывать наблюдения до нужных соотношений, сгенерировав случайные числа (номера, которые нужно выкинуть). 😄 #опросы #социология #survey #sav #spss #выборка
Решение - в лоб. Добавить переменную веса, для каждой группы свою, потом пристыковать в df и посчитать. Вручную прописать условие через ifelse: есть вектор a, где для 12 групп есть коэф. перевзвешивания. Тогда: i <- ifelse (dt$sex=='Мужской' & dt$age == '18-24',a[2],...) *коэф для мужчин 18-24 лет идёт вторым Выборки в соцопросах обычно до 2500~ тысяч человек, поэтому скорость тут не критична, но решение так себе. В идеале найти бы такую функцию, которая автоматически сопоставлла бы дата-фрейм/вектор с весами и выборку. #опросы #социология #survey #sav #spss #выборка
Звучит как задача на 3 строчки. Только датасеты надо сюда приложить. Картинки Reprex-ом не являются.
Она и есть на три строчки, по краней мере, в блок-схеме. Недостаточно знание синтаксиса препятствует, но я учу тихой сапой. + умение читать техническое описание функции, и связь функции с др. пакетами нужно знать, по идее
Датасеты в студию, плз.
Spss мало кого беспокоит и мало кто с ним работает. csv, как кроссплатформенный, был бы куда человечнее.
На hh видел много SPSS-а в отрасли маркетинговых исследований и социологии (если брать не топ-вакансии, но и там пару раз мелькало). В чате это уже обсуждали n лет назад.
Почитал про минимально воспроизводимый пример. Добавлю, чтобы внести ясность. #опросы #социология #survey #sav #spss #выборка Информацию по чтению и обработке .sav брал отсюда install.packages('heaven') library(haven) sexageN <- as_factor(read_sav('general_population.sav')) colnames(dt)[25:30] <- c('sex','age','location','child','educ','prosperity') dt <- as_factor(dt) sexage <- as.data.frame(table(dt$sex,dt$age)/12) #12 - это 1% sexage <- sexage [-c(1:2),] a <- as.vector(sexageN$Freq/sexage$Freq) # решение задачи перевзвешивания i <- ifelse (dt$sex=='Мужской' & dt$age == '18-24',a[1],0) #и так для каждой когорты dt <- cbind(dt,i) остаётся "выкинуть" наблюдения согласно "весу", чтобы количество пропорций sexage было как в sexageN. Продолжу думать над решением (как выкинуть), когда проснусь. Итоговый результат должен быть sexage = sexageN (N - это генеральная совокупность) Один из материалов по взвешиванию. Начинающим может быть интересно.
Sex и Age должны быть и в файле ГС и в микроданных выборочного файла. Ваш синтаксис с одними переменными, в sav другие. Если в согласованном виде представите файлы попробую показать как это дело в survey решается
так точно, проснусь - постараюсь сделать. Я там конспект уже начал вести своих мытарств. Надеюсь, когда-нибудь поможет таким же бедолагам
Александр, т.е. можно Ваш аккаунт в телеге переименовать в человеческий, опираясь на данные ссылки?
Вот две классические статьи с которых Хадли начинал думать про реафакторинг подходов в R. Для примера как раз похожие задачи и использовались.
как-то так r # по мотивам # https://www.r-bloggers.com/2018/12/survey-raking-an-illustration/ library(survey) # характеристики ГС ------------------------------------------------------- population <- data.frame( stringsAsFactors = FALSE, mood = c("happy", "neutral","grumpy","happy","neutral","grumpy","happy", "neutral","grumpy","happy","neutral", "grumpy","happy","neutral","grumpy","happy", "neutral","grumpy"), sex = c("female", "female","female","male","male","male","female", "female","female","male","male","male","female", "female","female","male","male","male"), age = c("young","young", "young","young","young","young","middle", "middle","middle","middle","middle","middle", "senior","senior","senior","senior","senior", "senior"), fraction = c(0.075,0.125, 0.05,0.075,0.125,0.05,0.06,0.1,0.04,0.06,0.1, 0.04,0.0165,0.0275,0.011,0.0135,0.0225, 0.009) ) # моделируем выборку ------------------------------------------------------ set.seed(1) mood <- sample( x = c("grumpy", "happy", "neutral"), size = 1000, replace = TRUE, prob = c(0.2, 0.3, 0.5) ) age <- sample( x = c("young", "middle", "senior"), size = 1000, replace = TRUE, prob = c(0.2, 0.7, 0.1) ) sex <- sample( x = c("male", "female"), size = 1000, replace = TRUE, prob = c(0.48, 0.52) ) response<- sample( x = c(1, 0), size = 1000, replace = TRUE, prob = c(0.4, 0.6) ) # предполагаем что это простая случайная выборка индивидов. # Поэтому базовый весовой коэффициент равен 1 (weight = 1) df_sample <- data.frame( mood = mood, sex = sex, response = response, age = age, weight = 1 ) # задаем план анализа выборки # игнорируем то, что выборка без замены (без возвращения) # ids = ~1 - означает, что отбор индивидов (не кластеров) dsrswr <- svydesign(ids = ~1, weights = ~weight, data = df_sample) # среднее значение переменной response svymean(x = ~response, design = dsrswr) #> mean SE #> response 0.398 0.0155 # т.к. дизайн анализа выборки самый простой (простая случайная выборка), # то это аналогично mean(df_sample$response) #> [1] 0.398 # poststartification ------------------------------------------------------ # В этой ситуации мы знаем размеры ГС для всех сочетаний категорий переменных # sex, mood, age (собственно это population) dsrswr_p <- postStratify( design = dsrswr, strata = ~ sex + mood + age, population = population ) # результат постстратификации svymean(x = ~response, design = dsrswr_p) #> mean SE #> response 0.3764 0.019 # raking ------------------------------------------------------------------ ### В этой ситуации мы знаем размеры ГС только отдельно для переменных # sex, mood, age. Размеры ГС по сочетаниям не знаем. # Т.е. знаем отдельно по sex, по age, а по sex*age не знаем # margins по ГС pop_mood <- xtabs(fraction ~ mood, population) pop_sex <- xtabs(fraction ~ sex, population) pop_age <- xtabs(fraction ~ age, population) dsrswr_r <- rake( design = dsrswr, sample.margins = list( ~ mood, ~ sex, ~ age), population.margins = list(pop_mood, pop_sex, pop_age) ) # результат рэкинга svymean(x = ~response, design = dsrswr_r) #> mean SE #> response 0.37805 0.0189 <sup>Created on 2022-05-18 by the [reprex package](https://reprex.tidyverse.org) (v2.0.1)</sup>
https://stats.oarc.ucla.edu/r/seminars/survey-data-analysis-with-r/ https://epirhandbook.com/en/survey-analysis.html https://slcladal.github.io/surveys.html
Спасибо! Подождем автора вопроса)
Спасибо за потраченное время, всем кто участвовал. Нашёл ещё такое решение через веб архив. Подробно пока не разбирал, изучаю ваше решение. https://web.archive.org/web/20160507012347/http://soc-research.info/blog/index_files/weights.html #опросы #социология #survey #sav #spss #выборка
я правильно понимаю, что потом мы из листа по итогам постстратификации просто вытаскиваем varibles и можем сделать их дата-фреймом или таблицей (если нужно сохранить итог в sav или дальше продолжить работать с дата.фреймом)?
можно просто вытащить веса weights("план_анализа_выборки_из_пакета_survey") и добавить их к вашему df
library (survey) library(haven) #просто преобразлвания, тут не так важно dt <- read_sav('test.sav') colnames(dt) colnames(dt)[25:30] <- c('sex','age','location','child','educ','prosperity') colnames(dt)[1:24] <- gsub("0", "", names(dt[1:24])) dt <- as_factor(dt) #ваяем таблицу сопряжённости для ГС и ВЫБОРКИ sexage <- as.data.frame(table(dt$sex,dt$age)/0.12) colnames(sexage)[1:2] <- c('sex','age') sexageN <- as_factor(read_sav('sexage.sav')) colnames(sexageN)[1:2] <- c('sex','age') #таблица изначально была представлена в процентах, перевожу в доли sexageN$Freq = sexageN$Freq/100 #добавляю к ГС "скрытые" страты, которые есть в dt sexageN <- rbind(sexage[1:2,],sexageN) #добавляю к ГС вес, как в примере weight <- rep(1,1200) dt <- cbind(dt,weight) #план анализа выборки dis <- svydesign(ids = ~1, weights = ~weight, data = dt) #постстратификация по sex + age postS <- postStratify( design = dis, strata = ~ sex + age, population = sexageN )
Не могу понять, почему выдаёт: Error in postStratify.survey.design(design = dis, strata = ~sex + age, : Strata in sample absent from population. This Can't Happen Вроде всё в нужный вид привёл и кол-во страт совпадает. Я даже специально в sexageN пришпандорил "скрытые" страты, которые есть в df.
Вроде всё срабатывает. Один вопрос не ясен weight = 1, это же не то же самое, что коэф веса? Это же вероятность попадания наблюдения/респондента в выборку или какой-то другой параметр? Я подробнее про выборки прочитал в различных источниках, но этот момент всё равно туманный. Ещё бывают местами разные условные названия одних и тех же вещей. Ну и такой ключевой вопрос. Мы ведь, по-большому счёту, коэфы веса для страт/категорий находим для корректировки таблиц сопряжённости, чтобы там были репрезентативные соотношения интересующих параметров, если какие-то группы представлены мало или избыточно. По итогу надо вывести таблицу сопряжённости с корректировкой на веса. Я пробовал, но столкнулся с проблемой. Например, мы выводим таблицу сопряжённости, а потом загоняем в дата-фрейм (для работы) вот таким макаром (i - это весовые коэффициенты, которые уже рассчитаны для 1200 строк): sopr <- data.frame(table(dt$age,dt$sex,dt$q1,dt$i)) sopr <- sopr[sopr$Freq != 0,] 1. составляю таблицу сопряжённости для возраста и пола, чтобы посмотреть ответы для разных категорий; 2. перевожу в data frame, чтобы было удобнее перемножить веса на частоту ответов по q1 для разных страт/категорий; 3. убираю "пустые" соотношения. После этого автоматически sopr$i переводит всё содержимое в факторы. И я не могу перемножить их на частоту sopr$Freq. Функция as.numeric в данном случае превращает i в набор цифр. UPD через пять часов активного гуглинга и майндфака нашёл простое решение as.numeric(as.character(sopr$i)) #социология #survey #sav #spss
Судя даже по приведенному образцу кода, у Вас далеко не самый лучший стиль кодирования, если выразиться помягче. Уверен, что много проблем проистекает из этого. Если нужна помощь, то публикуйте репрекс.
Я не в теме. Но мне кажется идея такая. Вы хотите что то сказать про популяцию. Но у вас есть какая то не-репрезентативная выборка. Вот эти весы делают вашу выборку репрезентативной
Попробую по-человечески представить вопрос чуть позже. Пока этот поинт удалять не буду, чтобы не забыть последовательность рассуждений.
Да, это пропорциональное взвешивание относительно страт/категорий N (ГС). В выборке n категории смещены относительно N. В данной задаче (это учебная задача, здесь опускается сам дизайн отбора респондентов) есть два путя коррекции - либо выкинуть наблюдения из страт случайным образом до нужных пропорций, либо рассчитать веса для половозрастных страт в n (где избыточно представлены, где недостаточно), чтобы делать поправку на них, когда анализируем другие параметры в таблицах сопряжённости и т.п. В моём случае эти параметры касаются электорального поведения. В excel эта задача, в общем-то, быстро решается. Но я пытаюсь силами R всё сделать, чтобы отработать "технику". Пример зачем веса нужны простой: допустим нужны итоги голосования, а какая-то категория населения в выборке представлена избыточно (и она влияет на результат). Мы составляем таблицу сопряжённости и умножаем результаты этой группы на корректирующий коэффициент (вес). Получаются данные более близкие к тому, что было бы в ГС.
да, weight и коэффициент веса одно и то же. Базовый выборочный вес обратно пропорционален вероятности отбора (w = 1/p). weight = 1 означает, что выборка равновероятностная (каждый объект имеет равную/одинаковую вероятность быть отобранным). В общем случае это не так. Потом этот базовый выборочный вес корректируют разными способами (даже статью Степанова нашли (скорее всего, единственная в русском сегменте)). Скажите, Вы в тему выборки решили основательно погружаться и изучать этот вопрос? Если решили серьезно заняться вопросом, то, возможно, стоит начать с основ. А Вы сразу в калибрацию "прыгнули". При все внешней простоте тема выборки не такая простая, как может показаться. Можно начать с уже рекомендованного "Основы построения выборки для социологических исследований: А. В. Чуриков"
и вы в R хотите считать или в SPSS? если в R, то практически уверен, что survey закроет 99% задач. Если SPSS, тогда осваивайте модуль complex sample ( "Сложные выборки" если русскоязычный интерфейс)
Юрий, поправьте, если я неправильно понимаю. Похоже, что вся соц. обработка технически сводится к сборке/размазыванию по тарелке. Аналог оригами (флексагон). Поглядел по диагонали. Такие манипуляции элементарно делаются тайдиверсом. А стат гипотезы проверять стат пакетами. Саму методику сбора я не затрагиваю. Но пока нет кода, так и будут часы гуглопоиска, нюанс с факторами это показывает явно. Я не пытаюсь упрощать, просто без формул и кода непонятно что решается. N измерений по разному атрибутированных раскладываются в разные чашечки. Каллах или миплплейсмент. Минимаксы, различные регрессии и пр. замечательно в р решаются же.
Фактически (упрощенно), да "сводится к сборке/размазыванию по тарелке". Основной задачей выборки это получение итогов ГС по выборочным микроданным. Т.е. получение общих итогов/агрегирование (сборка) + в интересующих разрезах разработки данных (скорее аналог микроскопа). 1. если нужны точечные оценки, то, да элементарно тайдиверсом сделать 2. если нужны показатели точности (доверительные интервалы/ошибки выборки), то там есть нюансы (начиная с дизайна выборки, который влияет на это). если нужен/важен п.2, то я бы всё-таки в связке tidyverse/data.table + survey решал задачи. про статпакеты. возьмем, например, t.test. расчет стандартной ошибки выборки ведется для случая простой случайной выборки. Используя survey можно/нужно учитывать сложные планы отбора выборок для оценки ошибок выборок и соответственно корректности расчетов тестов, например. p.s. сложный план отбора выборки - любой план отбора отличающийся от простой случайной выборки
Но такое то легко решается несколькими строчками тайдиверса или дататейбла.
Да, если копать сильно вниз, то всегда можно добраться до тонкой структуры. Вопрос в целесообразности в конкретном случае. Да и погружение должно идти сверху вниз, тонкие эффекты важны, когда в первых приближениях все гладко.
целесообразность в том, что очень просто ложно завысить точность оценивания в 3-4 и более раз, если мы работаем с данными как с простой случайной выборкой, когда на деле это не так. И это не преувеличение
или Вы про целесообразность погружения автора вопроса в тему выборки имеете ввиду?
Чурикова читать уже начал, хорошая наводка, спасибо. Потому что первые страницы запроса захламлены копирайтерскими статьями ни-о-чём и старыми статьями. По-хорошему, надо вообще с теорвера начинать :D Survey начал учить. Читаю тех. документацию и ссылки, которые вы скидывали на примеры из R-блохеров. Ну, без представления о реальных задачах хотя бы уровня "лох" сложновато карту обучения составлять. Так что такие мытарства - это норма, когда требуется комплексно приобретать навыки без руководителя. Но в этом есть и плюс — нет материальной ответственности за ошибки 😁
да, тервер лишним не будет. Но как-то думал, что его основы есть по умолчанию. Что касается задач, то лучше с микроданными обследований попробовать работать. 1. микроданные выборочных наблюдений Росстата https://www.gks.ru/free_doc/new_site/inspection/itog_inspect1.htm Рекомендую "Выборочное наблюдение доходов населения и участия в социальных программах" 2. RLMS https://www.hse.ru/rlms/ Микроданные там после регистрации можно скачать Для RLMS как раз пример с постстратификацией/рэкингом в тему. Есть там в базе переменная постстратификационного веса. И выборка там как раз как равновзвешенная строилась в свое время.
про survey. Там основной принцип такой (1) задаем план анализа выборки svydesign (2) получаем оценки параметров ГС svymean, svytotal и прочее
ну и если за survey взялись, то также рекомендую поискать материалы автора библиотеки. Lumley Thomas. Complex sampling and R
Обсуждают сегодня