Stata - 根据变量中的值分配不同的变量

时间:2014-01-30 19:42:07

标签: 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循环。像这样的东西。

  forvalues i = 1/20 {
     replace variable[`order`i'value] = 1 

  }

感谢您的帮助!

*****澄清2月2日增加。** 我简化了我的问题和数据集太多bc解决方案建议我所提出的工作,但是,没有得到我真正想要做的事情。谢谢你们的解决方案。我的帖子里我不够清楚。

为了澄清,我的数据与每个订单没有一对一的对应关系#如果没有丢失则分配变量#a 1。例如,对order1 = 3的第一次观察,变量1不应该得到1,变量3应该得到1.我在原始帖子中没有包含的内容是我实际上正在检查其他条件来设置它等于1。

对于更多背景,我按照出生顺序(第一个孩子,第二个孩子等)在不同年龄的母亲身上计算出生女性。所以在数据中,每一行都是一个女人,每个订单#都是出生人数(order1 = 3,这是她的第三个孩子)。相应的变量#s是计数(变量#表示女性有出生顺序的孩子#)。我在帖子中提到过,我这样做了9次,我正在为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;如果order1 = 2,那么变量[agegroup] [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
  }
 }

3 个答案:

答案 0 :(得分:2)

我会reshape两次。首先reshapelong,然后在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 |
*     +-----------------------------------------------------------+

答案 1 :(得分:2)

使用forvaluesgenerate的简单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是简单gentimer 2 reshapetimer 3 egen, rowmax()timer 4原始交。

你只需要一个循环的原因是Stata的方法是对数据库中的所有观察执行命令,从顶部(第一次观察)到底部(最后一次观察)。例如,生成variable1但是根据order1是否缺失;这是针对两个变量的所有观察完成的,没有显式循环。

我想知道你是否真的需要这样做。对于未来的问题,如果您有进一步的目标,我认为一个好的策略是在您的帖子中提及它。

注意:我重复使用了其他海报的答案。

答案 2 :(得分: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'
}