Как заставить postfile работать как со строковой, так и с числовой переменной

#stata #postfile

#stata #postfile

Вопрос:

Я пытаюсь написать программу Stata, которая выполняет некоторые вычисления по идентификатору, и я хочу сделать это так, чтобы идентификатор мог быть либо строковым, либо целым числом.

Сильно упрощенная версия того, что я пытаюсь сделать, выглядит следующим образом:

 clear all

***** test data
input str10 id1 id2 x y
a   1   20  40
a   1   140 20
a   1   0   70
b   2   50  25
b   2   25  50
b   2   40  42
end

*****
capture program drop myprog
program define myprog
    version 14.2
    syntax using, ID(varname) Mean(varname)
    tempname postname

    quietly levelsof `id', local(ids)
    local idtype: type `id'

    postfile `postname' `idtype' `id' `mean' `using', replace


    foreach i of local ids {
        quietly summarize `mean' if `id'==`i'
        post `postname' (`i') (`r(mean)')
    }

    postclose `postname'
end
  

И я ожидаю, что сработают оба следующих действия:

 myprog using "test1.dta", id(id1) mean(x)
myprog using "test2.dta", id(id2) mean(x)
  

Есть какие-нибудь советы?

Ответ №1:

Просто используйте оператор if / else , чтобы различать два случая:

 capture program drop myprog
program define myprog
    version 14.2
    syntax using, ID(varname) Mean(varname)
    tempname postname

    quietly levelsof `id', local(ids)
    local idtype: type `id'

    postfile `postname' `idtype' `id' `mean' `using', replace

    if substr("`idtype'" , 1, 3) == "str" {
        foreach i of local ids {
            summarize `mean' if `id'=="`i'", meanonly 
            post `postname' ("`i'") (`r(mean)')
        }
    } 
    else {
        foreach i of local ids { 
            summarize `mean' if `id'==`i', meanonly 
            post `postname' (`i') (`r(mean)')       
        }
    }

    postclose `postname'
end
  

Кстати, обратите внимание на использование meanonly опции summarize .

Комментарии:

1. Спасибо! Оказывается, мне потребовалось всего 10 минут, чтобы отойти от своего ответа в Google, и в итоге я сделал что-то похожее на то, что сделали вы.

Ответ №2:

Вот что я в итоге сделал:

 capture program drop myprog
program define myprog
    version 14.2
    syntax using, ID(varname) Mean(varname)
    tempname postname

    quietly levelsof `id', local(ids)
    local idtype: type `id'
    postfile `postname' `idtype' `id' `mean' `using', replace

    capture confirm string variable `id'

    if !_rc {
        foreach i of local ids {
            quietly summarize `mean' if `id'=="`i'"
            post `postname' ("`i'") (`r(mean)')
        }
    }
    else {
        foreach i of local ids {
            quietly summarize `mean' if `id'==`i'
            post `postname' (`i') (`r(mean)')
        }
    }

    postclose `postname'
end
  

Два почти идентичных цикла выглядят некрасиво, но я думаю, что это нормально.

Комментарии:

1. Смотрите пересмотр ответа @ Pearly Spencer, который стал ближе к вашему. Вы также могли бы использовать egen newid = group(id), label , а затем опубликовать метки значений newid , которые всегда являются строковыми. Таким образом, был бы только один цикл.

2. Хорошее предложение. К сожалению, в моем реальном варианте использования я буду объединять результаты postfile обратно в другой «основной» набор данных, и мне придется сохранить тип данных.