Частота взвешивания в R, сравнивая результаты с Stata
Я пытаюсь проанализировать данные из набора данных IPUMS Университета Миннесоты для 1990 США переписи в R
. Я использую пакет survey
, потому что данные Взвешенный. Просто беря данные домохозяйства (и игнорируя переменные человека, чтобы все было в порядке), я пытаюсь вычислить среднее значение hhincome
(доходы домашних хозяйств). Для этого я создал объект дизайна съемки, используя svydesign()
со следующим кодом:
> require(foreign)
> ipums.household <- read.dta("/path/to/stata_export.dta")
> ipums.household[ipums.household$hhincome==9999999, "hhincome"] <- NA # Fix missing
> ipums.hh.design <- svydesign(id=~1, weights=~hhwt, data=ipums.household)
> svymean(ipums.household$hhincome, ipums.hh.design, na.rm=TRUE)
mean SE
[1,] 37029 17.365
Пока все хорошо. Тем не менее, я получаю другую стандартную ошибку, если я попытаюсь выполнить один и тот же расчет в Stata
(используя предназначенный для другой части одного и того же набора данных):
use "C:\I\Hate\Backslashes\stata_export.dta"
replace hhincome = . if hhincome == 9999999
(933734 real changes made, 933734 to missing)
mean hhincome [fweight = hhwt] # The code from the link above.
Mean estimation Number of obs = 91746420
--------------------------------------------------------------
| Mean Std. Err. [95% Conf. Interval]
-------------+------------------------------------------------
hhincome | 37028.99 3.542749 37022.05 37035.94
--------------------------------------------------------------
И, глядя на другой способ обмануть этого кота, автор survey
, имеет это предложение для взвешивания по частоте:
expanded.data<-as.data.frame(lapply(compressed.data,
function(x) rep(x,compressed.data$weights)))
Однако я не могу заставить этот код работать:
> hh.dataframe <- data.frame(ipums.household$hhincome, ipums.household$hhwt)
> expanded.hh.dataframe <- as.data.frame(lapply(hh.dataframe, function(x) rep(x, hh.dataframe$hhwt)))
Error in rep(x, hh.dataframe$hhwt) : invalid 'times' argument
Что я не могу исправить. Это может быть связано с this issue.
Итак, в сумме:
- Почему бы мне не получить одинаковые ответы в
Stata
и R
?
- Какой из них прав (или я делаю что-то неправильно в обоих случаях)?
- Предполагая, что я получил решение
rep()
, будет ли репликация результатов Stata
?
- Что такое правильный способ сделать это? Кудо, если ответ позволяет мне использовать
plyr
пакет для выполнения произвольных вычислений, а не ограничиваться функции, реализованные в survey
(svymean()
, svyglm()
и т.д.)
Update
Итак, после отличной помощи, которую я получил здесь и из IPUMS по электронной почте, я использую следующий код для правильной обработки взвешивания опроса. Я опишу здесь, если у кого-то еще есть эта проблема в будущем.
Подготовка исходных стат
Поскольку IPUMS в настоящее время не публикуют сценарии для импорта своих данных в R
, вам нужно начать с Stata
, SAS
, или SPSS
. На данный момент я придерживаюсь Stata
. Начните с запуска импорта script из IPUMS. Затем перед продолжением добавьте следующую переменную:
generate strata = statefip*100000 + puma
Это создает уникальное целое число для каждого PUMA
формы 240001 с первыми двумя цифрами в качестве кода состояния fipt (24 в случае Maryland) и последних четырех a PUMA
id, который является уникальным для каждого государственной основе. Если вы собираетесь использовать R
, вам также может быть полезно также запустить его
generate statefip_num = statefip * 1
Это создаст дополнительную переменную без меток, так как импорт .dta
файлов в R
применит метки и потеряет основные целые числа.
Stata и svyset
Как объяснил Кейт, выборка опроса обрабатывается Stata
, вызывая svyset
.
Для индивидуального анализа уровня я теперь использую:
svyset serial [pweight=perwt], strata(strata)
Это устанавливает весовое значение perwt
, стратификацию переменной, которую мы создали выше, и использует семейный номер serial
для учета кластеризации. Если мы используем несколько лет, мы можем попробовать
generate double yearserial = year*100000000 + serial
для учета продольной кластеризации.
Для анализа уровня домохозяйства (без лет):
svyset serial [pweight=hhwt], strata(strata)
Должно быть понятно (хотя я думаю, что в этом случае сериал на самом деле лишний). Замена serial
на yearserial
будет учитывать временной ряд.
Выполнение этого в R
Предполагая, что вы импортируете файл .dta
с дополнительной переменной strata
, описанной выше, и анализируя по отдельной букве:
require(foreign)
ipums <- read.dta('/path/to/data.dta')
require(survey)
ipums.design <- svydesign(id=~serial, strata=~strata, data=ipums, weights=perwt)
Или на уровне домохозяйства:
ipums.hh.design <- svydesign(id=~serial, strata=~strata, data=ipums, weights=hhwt)
Надеюсь, что кто-то найдет это полезным, и так благодарит Dwin, Keith и Brandon от IPUMS.
Ответы
Ответ 1
1 & 2) Комментарий, который вы цитировали от Lumley, был написан в 2001 году и предшествует любой из его опубликованных работ с пакетом опроса, который вышел всего несколько лет. Вероятно, вы используете "веса" в двух разных смыслах. (Lumley описывает три возможных чувства в начале своей книги.) Функция опроса svydesign использует весовые коэффициенты вероятности, а не весовые коэффициенты. Похоже, что это не действительно весовые коэффициенты, а скорее весовые коэффициенты вероятности, учитывая массивный размер этого набора данных, и это будет означать, что результат опроса верен, а результат Stata неверен. Если вы не уверены, тогда пакет опроса предлагает функцию as.svrepdesign(), с помощью которой книга Lumley описывает, как создать репликативный вектор веса из объекта svydesign.
3) Я так думаю, но, как сказал RMN... "Это было бы неправильно".
4) Так как это неправильно (IMO), это не обязательно.
Ответ 2
Вы не должны использовать частотные веса в Stata. Это довольно ясно. Если IPUMS не имеет "сложного" проекта съемки, вы можете просто использовать:
mean hhincome [pw = hhwt]
Или, для удобства:
svyset [pw = hhwt]
svy: mean hhincome
svy: regress hhincome `x'
Какая приятная информация о втором варианте заключается в том, что вы можете использовать его для более сложных схем съемки (с помощью опций svyset. может запускать множество команд без необходимости использовать тип [pw...] все время.
Ответ 3
Небольшое дополнение для людей, которые не имеют доступа к Stata или SAS; (Я бы поставил это в комментариях, но...)
Библиотека SAScii может использовать файл кода SAS для чтения в загруженных данных IPUMS. Код для чтения в данных из doc
library(SAScii)
IPUMS.file.location <- "..\\usa_00007dat\\usa_00007.dat"
IPUMS.SAS.read.in.instructions <- "..\\usa_00007dat\\usa_00007.sas"
#store the IPUMS extract as an R data frame!
IPUMS.df <-
read.SAScii (
IPUMS.file.location ,
IPUMS.SAS.read.in.instructions ,
zipped = F )