我列出了每个公司的开始和结束日期。我想计算一段时间内活着的公司数量。我有以下代码,但它在我的大数据集上运行缓慢。在Stata中有更有效的方法吗?
forvalues y = 1982/2012 {
forvalues m = 1/12 {
*display date("01-`m'-`y'","DMY")
count if start_dt <= date("01-`m'-`y'","DMY") & date("01-`m'-`y'","DMY") <= end_dt
}
}
答案 0 :(得分:1)
一种方法是使用inrange
功能。在Stata中,Date
变量只是整数,因此您可以轻松地对它们进行操作。
forvalues y = 1982/2012 {
forvalues m = 1/12 {
local d = date("01-`m'-`y'","DMY")
count if inrange(`d', start_dt, end_dt)
}
}
仅此一项就可以为您节省大量时间。对于50.000观察(和补偿数据):
. timer list 1
1: 3.40 / 1 = 3.3980
. timer list 2
2: 18.61 / 1 = 18.6130
计时器1 使用inrange
,计时器2 是您的原始代码。结果以秒为单位。有关详细信息,请运行help inrange
和help timer
。
也就是说,也许有人可以提出一个更好的策略。
答案 1 :(得分:1)
假设一个公司标识符firmid
,这是另一种思考问题的方法,但具有不同的数据结构。在执行此操作之前,请确保已保存数据集的副本。
expand 2
bysort firmid : gen eitherdate = cond(_n == 1, start_dt, end_dt)
by firmid : gen score = cond(_n == 1, 1, -1)
sort eitherdate
gen living = sum(score)
by eitherdate : replace living = living[_N]
所以,
我们expand
每次观察到2并将两个日期放在一个新变量中,一个观察中的开始日期和另一个观察中的结束日期。
我们指定一个公司开始时的分数为1,结束时的分数为-1。
每次公司开始时,公司数量增加1,每次结束时公司数量减少1。我们只需要按日期排序,公司数量就是这些分数的累积总和。 (编辑:在同一天更改了修改。)
这种新的数据结构可用于其他目的。
在http://www.stata-journal.com/article.html?article=dm0068
上写了一篇文章编辑:
回应@Roberto Ferrer(及其他读过此内容的人)的注释:
我修复了一个错误的错误,这让人很难理解。对于那个很抱歉。
这里使用的日期只是公司开始和结束的日期。在任何其他日期评估公司数量没有明显的意义,因为它与前一个日期的数字相同。但是,如果您需要插入日期网格,则复制先前的计数就足够了。
重要的是不要混淆返回累积和的Stata函数sum()
与任何egen
函数。 egen
的{{1}}是替代方案的印象是我的错误的副作用。