Как возникают различия между общими расчетами в длинном формате с использованием Stata

Иногда я использую несколько раздутый подход к созданию переменных в Stata, когда работаю с временными рядами или панельными данными в длинной форме: я создаю много новых переменных в широкой форме данных, фактически поддерживая длинную форму данных. Имея такой раздутый набор данных, есть два разных способа создать общую переменную, которая суммирует эти переменные, используя либо egen = rowtotal(varlist), либо by varlist: egen = total(exp). Однако использование compare показывает, что эти два способа дают минимально разные результаты. Как возникают эти различия?

Вот рабочий пример:

webuse grunfeld, clear
drop if year < 1950

*** Totals using new variables in wide data shape for each year ***
gen invest50 = invest if year==1950
gen invest51 = invest if year==1951
gen invest52 = invest if year==1952
gen invest53 = invest if year==1953
gen invest54 = invest if year==1954
bysort company: replace invest50 = invest50[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1950
bysort company: replace invest51 = invest51[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1951
bysort company: replace invest52 = invest52[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1952
bysort company: replace invest53 = invest53[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1953
gsort company -year
bysort company: replace invest51 = invest51[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1951
bysort company: replace invest52 = invest52[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1952
bysort company: replace invest53 = invest53[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1953
bysort company: replace invest54 = invest54[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1954
sort company year
egen totin1 = rowtotal(invest50 invest51 invest52 ///
    invest53 invest54) 

*** Totals using variables in long data shape and by-option ***
bysort company (year): egen totin2 = total(invest)

desc tot*
compare totin1 totin2

person non-numeric_argument    schedule 25.08.2014    source источник


Ответы (1)


Здесь важна числовая точность. Используйте double для получения "точных" результатов:

webuse grunfeld, clear
drop if year < 1950

keep company invest year

*** Totals using new variables in wide format for each year ***
gen double invest50 = invest if year==1950
gen double invest51 = invest if year==1951
gen double invest52 = invest if year==1952
gen double invest53 = invest if year==1953
gen double invest54 = invest if year==1954

bysort company: replace invest50 = invest50[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1950

bysort company: replace invest51 = invest51[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1951

bysort company: replace invest52 = invest52[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1952

bysort company: replace invest53 = invest53[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]>1953

gsort company -year

bysort company: replace invest51 = invest51[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1951

bysort company: replace invest52 = invest52[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1952

bysort company: replace invest53 = invest53[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1953

bysort company: replace invest54 = invest54[_n-1] ///
    if company[_n]==company[_n-1] & year[_n]<1954

sort company year

egen double totin1 = rowtotal(invest50 invest51 invest52 ///
    invest53 invest54) 

*** Totals using variables in long format and by-option ***

bysort company (year): egen double totin2 = total(invest)

desc tot*
compare totin1 totin2

Результаты

              storage  display     value
variable name   type   format      label      variable label
-----------------------------------------------------------------------------------------------
totin1          double %10.0g                 
totin2          double %10.0g                 

. compare totin1 totin2

                                        ---------- difference ----------
                            count       minimum      average     maximum
------------------------------------------------------------------------
totin1=totin2                  50
                       ----------
jointly defined                50             0            0           0
                       ----------
total                          50

См. http://blog.stata.com/2011/06/17/precision-yet-again-part-i/ и ссылки в нем.

person Roberto Ferrer    schedule 25.08.2014
comment
Я действительно сталкиваюсь со старой проблемой формата float? Проклятие. По крайней мере, я уже знаю, что раздутый первый вариант слишком часто округлялся по сравнению с коротким вторым вариантом. - person non-numeric_argument; 25.08.2014
comment
float — это переменная (тип хранилища), а не формат. Формат слова здесь сильно перегружен. Я предлагаю говорить о широкой или длинной форме данных или структуре данных, хотя недоразумения по этому поводу кажутся редкими. (Тем не менее, long также является типом хранилища в Stata.) - person Nick Cox; 25.08.2014
comment
@NickCox Спасибо за разъяснение, я отредактировал свой вопрос, но больше не могу редактировать свой комментарий. - person non-numeric_argument; 04.09.2014
comment
Я думаю, вам нужно разъяснить, чем ваш вопрос теперь отличается и что вас не удовлетворяет в ответе Роберто Феррера. В частности, вы не суммируете то, что, по вашему мнению, показывает ваш код. - person Nick Cox; 04.09.2014
comment
Как показывает история изменений, вопрос на самом деле не изменился. В оригинальном постере изменена только терминология. - person Roberto Ferrer; 04.09.2014