计算Stata中不同条件下的观察结果

时间:2015-01-09 17:17:27

标签: stata matching

我有一个具有以下结构的大型数据集(这是一个例子):

+-----------------------------------------+
| id       date   treat   match   num     |
|-----------------------------------------|
|  1  01feb2000       1       2      2    |
|  1  01apr2000       0       .      .    |
|  1  01jan2002       1       3      1    |
|-----------------------------------------|
|  2  01mar2000       1       3      0    |
|  2  01may2000       0       .      .    |
|-----------------------------------------|
|  3  01dec2002       1       .      .    |
+-----------------------------------------+

对于由id标识的每个组,我在某些日期有某些事件。每次出现都是治疗或对照。每个治疗观察与某个id匹配。您可以按照给定的iddatetreatmatch变量。

我的目标是为实际匹配的每个治疗观察计算num的值(可能存在治疗观察不匹配的情况,请参阅id 3)。 规则是在处理后的观察日期之后的一年内计算匹配的id中的任何事件的数量(无论是否被处理)。

示例:第一次接受治疗的观察结果与id匹配。id 2在2000年2月1日之后的明年内有两次观察。

重要事项:首先,匹配ID中第一次出现的日期绝不会在考虑的治疗观察日期之前。其次,几个治疗观察可以与相同的id匹配。

请注意,此处here已提出类似问题。在这里,我关注算法的效率,因为我的数据集非常庞大。我的解决方案如下:

gen NUM = .
gen yrafter = 25000    // arbitrary date outside of the panel
format yrafter %td
gen in_window = 0
sort id date

forval i = 1/`=_N' {
    if (match[`i'] != .) {
        replace yrafter = (date_installation[`i'] + 365) if ags == match[`i']
            replace in_window = date_installation <= yrafter & ags == match[`i']

            by id: egen NUM_temp = sum(in_window) if ags == match[`i']
            replace NUM_temp = 0 if NUM_temp == .
            sum NUM_temp if ags == match[`i'], meanonly

            replace NUM0 in `i' = r(max)
        drop NUM_temp

        replace in_window = 0 if ags == match[`i']
    }
}

drop yrafter in_window

为了减少迭代次数,我实际上想要在处理观察之后进行排序,并且只迭代它们。但是,在我对这个问题的理解中,我无法做到这一点,因为一些后续的命令需要我上面已经应用的排序(我对吗?)。

我的策略是迭代每个相关观察:对于匹配的id组中的所有观察,我将yrafter的值替换为需要考虑的最新可能事件。然后在变量in_window中,我只是识别出最新可能日期之前的那些观察结果(记住,在treatment变量的日期之前不会发生任何事件),然后计算所有这些日期。我将结果保存在num中并为下一次迭代设置所有内容。

显然,这需要很多时间。我的第一个猜测是优化循环头,因为检查if条件对于Stata来说似乎非常耗时。有没有人有优化的想法?

2 个答案:

答案 0 :(得分:0)

只有在我有正确的代码时才会担心效率问题。以下是错误。

是非法的,应该可能是

    replace NUM0 = r(max) in `i' 

我无法对您的主要问题发表评论,因为我不明白您的目的是什么。我想你的解释清楚而合乎逻辑;当我从来没有做过类似的事情时,我太过复杂,无法吸收你正在做的事情。

答案 1 :(得分:0)

尝试一下

的内容
clear
set more off

*----- example data -----

input ///
 id  str20 date   treat   match   num     
  1  01feb2000       1       2      2    
  1  01apr2000       0       .      .    
  1  01jan2002       1       3      1    
  2  01mar2000       1       3      0    
  2  01may2000       0       .      .    
  3  01dec2002       1       .      .    
end

list, sepby(id)

gen dat = date(date,"DMY")
format %td dat
drop date
order dat, after(id)

list, sepby(id)

*----- what you want -----

gen num2 = .
forvalues i = 1/`=_N' {
    if treat[`i'] == 1 {
        count if id == match[`i'] & dat <=  dat[`i'] + 365
        replace num2 = r(N) in `i'
    }
}
replace num2 = . if missing(match)

list, sepby(id)

assert num == num2

我没有关于数据集大小的信息,所以除非你精确地透露,否则我不会做任何测试。

(我没有检查你的代码。我只是尝试将问题的措辞翻译成Stata代码。)