2014-01-30 6 views
1

Извините, что заголовок сбивает с толку. Надеюсь, это будет ясно ниже.Stata - назначить разные переменные в зависимости от значения внутри переменной

Я использую Stata, и я хотел бы присвоить значение 1 переменной, которая зависит от значения в другой переменной. У меня есть 20 переменных порядка, а также 20 соответствующих переменных. Например, если order1 = 3, я бы хотел назначить variable3 = 1. Ниже приведен фрагмент того, как будет выглядеть конечный набор данных, если бы у меня было только 3 каждой переменной.

enter image description here
Прямо сейчас я делаю это с двумя петлями, но я должен другую петлю вокруг этого, что проходит через это более 9 раз плюс я делал это в течение файлов данных несколько сотен. Я бы хотел сделать его более эффективным.

forvalues i = 1/20 { 
    forvalues j = 1/20 { 
    replace variable`j' = 1 if order`i'==`j' 
    } 
    } 

Можно ли использовать значение order'i»присвоить переменной [order`i'VALUE] напрямую? Тогда я могу избавиться от j цикла выше. Что-то вроде этого.

Благодарим за помощь!

***** ОБРАТНАЯ СВЯЗЬ добавлена ​​2 февраля. ** Я упростил свою проблему и набор данных слишком много, чтобы предлагаемые решения работали над тем, что я представил, но не добиваемся того, что я действительно пытаюсь сделать. Спасибо вам три за ваши решения. Я не был достаточно ясен в своем посте.

Чтобы уточнить, у моих данных нет взаимно-однозначного соответствия каждому порядку #, назначая переменную # a 1, если она отсутствует. Например, первое наблюдение для order1 = 3, variable1 не должно получать 1, переменная3 должна получить 1. Что я не включил в свой первоначальный пост, так это то, что я фактически проверяю другие условия, чтобы установить его равный 1.

Для получения дополнительной информации я подсчитываю рождение женщин по рождению (1-й ребенок, 2-й ребенок и т. д.), которые произошли в разное время матерей. Таким образом, в данных каждая строка - женщина, каждый заказ № - число рождений (order1 = 3, это ее третий ребенок). Соответствующей переменной # s являются подсчеты (переменная # означает, что у женщины есть ребенок порядка рождения №). Я упомянул в сообщении, что я делаю это 9 раз. Bc Я делаю это для 5-летних возрастных групп (15-19, 20-24 и т. Д.). Таким образом, первый набор переменных # был бы числом рождения по порядку, когда женщины были в возрасте 15-19 лет; второй набор переменных # был бы числом рождения по порядку, когда женщины были 20-24. и т. д. После этого я подытоживаю подсчеты по-разному (по образованию женщины, географии и т. д.).

Так с дополнительной петлей, что я делаю что-то больше, как это

forvalues k = 1/9{ 
    forvalues i = 1/20 { 
    forvalues j = 1/20 { 
    replace variable`k'_`j' = 1 if order`i'==`j' & age`i'==`k' & birth_age`i'<36 
    } 
    } 
} 

Не уверен, если это возможно, но я хотел бы упростить, поэтому мне нужно только, чтобы перебрать каждый ребенок один раз, не езду на велосипеде через заказы на рождение и напрямую использовать значение в порядке #, чтобы присвоить 1 правильной переменной. Поэтому, если order1 = 3 и у женщины был ребенок в конкретной возрастной группе, назначьте переменную [agegroup] [3] = 1; если Заказ1 = 2, то переменная [возрастная группа] [2] должны получить 1.

forvalues k=1/9{ 
    forvalues i = 1/20 { 
    replace variable`k'_[`order`i'value] = 1 if age`i'==`k' & birth_age`i'<36 
    } 
} 
+0

Вы хотите только отметить (с 1 по) без отсутствующих наблюдений? –

+0

Я хотел бы отметить все наблюдения с помощью 1 или 0. Все отсутствующие переменные порядка # получают 0 (я уже установил начальное значение переменных 0 в код, не показанный здесь). – Michelle

+0

Спасибо, что поделились своими решениями! Наконец-то я получил возможность внимательно посмотреть на эти должности, и я слишком сильно упрочил свою проблему. Я добавил изменения в свой оригинальный пост, чтобы уточнить. – Michelle

ответ

2

Я бы reshape дважды. Сначала reshape до long, затем условие variable по !missing(order), затем reshape назад к wide.

* generate your data 
clear 
set obs 3 
forvalues i = 1/3 { 
    generate order`i' = . 
     local k = (3 - `i' + 1) 
     forvalues j = 1/`k' { 
      replace order`i' = (`k' - `j' + 1) if (_n == `j') 
     } 
} 
list 


*. list 
* 
*  +--------------------------+ 
*  | order1 order2 order3 | 
*  |--------------------------| 
* 1. |  3  2  1 | 
* 2. |  2  1  . | 
* 3. |  1  .  . | 
*  +--------------------------+ 

* I would rehsape to long, then back to wide 
generate id = _n 
reshape long order, i(id) 
generate variable = !missing(order) 
reshape wide order variable, i(id) j(_j) 
order order* variable* 
drop id 
list 


*. list 
* 
*  +-----------------------------------------------------------+ 
*  | order1 order2 order3 variab~1 variab~2 variab~3 | 
*  |-----------------------------------------------------------| 
* 1. |  3  2  1   1   1   1 | 
* 2. |  2  1  .   1   1   0 | 
* 3. |  1  .  .   1   0   0 | 
*  +-----------------------------------------------------------+ 
+0

спасибо, что я попробую и посмотрю, ускорит ли она мою программу вообще. – Michelle

2

Используя простой forvalues цикл с generate и missing() на несколько порядков быстрее, чем другие предлагаемых решений (до сих пор). Для этой проблемы вам нужен только один цикл, чтобы пройти полный список переменных, а не два, как в исходном сообщении. Ниже приведен код, который показывает обе точки.

*----------------- generate some data ---------------------- 

clear all 
set more off 

local numobs 60 

set obs `numobs' 

quietly { 
forvalues i = 1/`numobs' { 
    generate order`i' = . 
     local k = (`numobs' - `i' + 1) 
     forvalues j = 1/`k' { 
      replace order`i' = (`k' - `j' + 1) if (_n == `j') 
     } 
} 
} 

timer clear 

*------------- method 1 (gen + missing()) ------------------ 

timer on 1 

quietly { 
    forvalues i = 1/`numobs' { 
     generate variable`i' = !missing(order`i') 
    } 
} 

timer off 1 

* ----------- method 2 (reshape + missing()) --------------- 

drop variable* 

timer on 2 

quietly { 
    generate id = _n 
    reshape long order, i(id) 
    generate variable = !missing(order) 
    reshape wide order variable, i(id) j(_j) 
} 

timer off 2 

*--------------- method 3 (egen, rowmax()) ----------------- 

drop variable* 

timer on 3 

quietly { 
// loop over the order variables creating dummies 
forvalues v=1/`numobs' { 
    tab order`v', gen(var`v'_) 
} 


// loop over the domain of the order variables 
// (may need to change) 
forvalues l=1/`numobs' { 
    egen variable`l' = rmax(var*_`l') 
    drop var*_`l' 
} 
} 

timer off 3 

*----------------- method 4 (original post) ---------------- 

drop variable* 

timer on 4 

quietly { 
forvalues i = 1/`numobs' { 
    gen variable`i' = 0 

    forvalues j = 1/`numobs' { 
     replace variable`i' = 1 if order`i'==`j' 
    } 
} 
} 

timer off 4 

*----------------------------------------------------------- 

timer list 

В таймерные процедуры дают

. timer list 
    1:  0.00/  1 =  0.0010 
    2:  0.30/  1 =  0.3000 
    3:  0.34/  1 =  0.3390 
    4:  0.07/  1 =  0.0700 

, где timer 1 является простой gen, timer 2reshape, timer 3egen, rowmax() и timer 4 исходное сообщение.

Причина, по которой вам нужен только один цикл, заключается в том, что подход Stata заключается в выполнении команды для всех наблюдений в базе данных, сверху (первое наблюдение) до нижней (последнее наблюдение). Например, генерируется variable1, но в соответствии с отсутствием или отсутствием order1; это делается для всех наблюдений обеих переменных без явного цикла.

Интересно, действительно ли вам нужно это делать. Для будущих вопросов, если у вас есть еще одна цель, я думаю, что хорошая стратегия - упомянуть об этом в вашем посте.

Примечание: Я повторно использовал код из ответов других плакатов.

+0

Ничего себе. Спасибо за бенчмаркинг. Мне нужно пересмотреть мою мантру «избегайте петель любой ценой». –

+0

Несомненно @RichardHerron. 'reshape' - это программа, которая, как представляется, требует слишком много работы для этой задачи. Запустите 'viewsource reshape.ado' и проверьте сами. Что-то подобное, я думаю, происходит с 'egen, rowmax()'. –

1

Вот простой способ сделать это (что по-прежнему требует 2 петли):

// loop over the order variables creating dummies 
forvalues v=1/20 { 
    tab order`v', gen(var`v'_) 
} 


// loop over the domain of the order variables (may need to change) 
forvalues l=1/3 { 
    egen variable`l' = rmax(var*_`l') 
    drop var*_`l' 
} 
+0

Есть две проблемы с этим. 1) В зависимости от количества наблюдений/переменных (и версии Stata) он быстро достигнет предела для разрешенного числа переменных (например, 70 obs/vars с Stata IC). 2) Опять же, в зависимости от количества obs/vars, это может быть медленнее, чем решение 'reshape' (например, 60 obs/vars). –

Смежные вопросы