我使用的面板数据包含几家公司(id
),涵盖了从2008年1月1日到2013年1月1日(date
,year
)这段时间。我想生成新的变量(sum1
),其中包含每个公司和特定时间间隔的var1
的每日观察总和。如果间隔等于每一年,我将使用函数total()
bysort id year: egen sum1=total(var1)
然而,在我的例子中,时间间隔被确定为两个事件之间的间隔。我有一个名为event
的特殊变量,如果事件在特殊日期发生,则该变量的值为1,否则该变量将丢失。每个公司都有5到10个活动。事件之间的间隔不相等;因此第一个间隔可以包含60个观察值,下一个间隔包含360个观察值。对于不同的公司,间隔也不相等。每个公司的第一个间隔的开始日期是1.1.2008。第二个间隔的开始日期是第一个事件的日期+1天。此外,我还想说明缺失值,因此如果公司x的var1
的所有值都是缺失变量,那么公司x和特定间隔的sum1
必须包含缺失值,而不是0。
我的面板看起来像这样:
id date year var1 event sum1(to gen) event_id(to gen)
1 1.1.2008 2008 25 . 95 (25+30+40) 1
1 2.1.2008 2008 30 . 95 (25+30+40) 1
...........................................................1
1 31.4.2008 2008 40 1 95 (25+30+40) 1
1 1.5.2008 2008 50 . 160 (50+50+60) 2
1 2.5.2008 2008 50 . 160 (50+50+60) 2
......................................... ................2
1 31.4.2009 2009 60 1 160 (50+50+60) 2
2 1.1.2008 2008 26 . 96 (26+30+40) 1
2 2.1.2008 2008 30 . 96 (26+30+40) 1
...........................................................1
2 31.6.2008 2008 40 1 96 (26+30+40) 1
2 1.5.2008 2008 51 . 161 (51+50+60) 2
2 2.5.2008 2008 50 . 161 (51+50+60) 2
...........................................................2
2 31.6.2009 2009 60 1 161 (51+50+60) 2
我试着写不同的循环(while
,if
),但是我做得不对。我不能使用rolling
,因为我的间隔不一样。
我的另一个想法是首先创建组标识符(称为event_id
),它包含每个间隔和每个公司的event_id
。然后我可以使用bysort id event_id: egen sum1=total(var1)
,但不幸的是我不知道如何做到这一点。因此,我的面板中的变量event_id
和sum1
并不存在,并且作为我想要实现的输出的示例。
发布于 2015-10-09 00:16:34
通过以下更改,我可以理解该示例:
4月31日和6月31日的
也就是说,一个倒转时间的技巧使得细分成咒语变得很容易。给定每个咒语的ends的标记1,我们就可以使用sum()
向后累积。这里关键的小细节是sum()
忽略缺少的值,或者更准确地说,将它们视为零。在这里,这完全是一个特性,尽管不完全是OP在应用egen, total()
时想要的。
然后反转拼写编号,将时间反转到正常方向,并像在其他答案中一样应用egen
。Reversing和reversing back都是使用-
进行的否定。在面板中对日期进行排序只是表面上的,一旦我们有了咒语的划分,但仍然是正确的事情。
有关Stata中的法术的更多信息,请参阅here
关于如何使用dataex
(SSC)提供数据示例的Statalist的提示,也适用于这里,只需稍作修改,请参阅here
clear *
input id str10 date year var1 event DesiredSum
1 1.1.2008 2008 25 . 95
1 2.1.2008 2008 30 . 95
1 30.4.2008 2008 40 1 95
1 1.5.2008 2008 50 . 160
1 2.5.2008 2008 50 . 160
1 30.4.2009 2009 60 1 160
2 1.1.2008 2008 26 . 96
2 2.1.2008 2008 30 . 96
2 30.4.2008 2008 40 1 96
2 1.5.2008 2008 51 . 161
2 2.5.2008 2008 50 . 161
2 30.6.2009 2009 60 1 161
end
gen ddate = -daily(date, "DMY")
bysort id (ddate): gen EVENT = sum(event)
replace ddate = -ddate
by id: replace EVENT = EVENT[_N] - EVENT + 1
bysort id EVENT (ddate): egen Sum = total(var1), missing
assert Sum == DesiredSum
list, sepby(id EVENT)
+-----------------------------------------------------------------------+
| id date year var1 event Desire~m ddate EVENT Sum |
|-----------------------------------------------------------------------|
1. | 1 1.1.2008 2008 25 . 95 17532 1 95 |
2. | 1 2.1.2008 2008 30 . 95 17533 1 95 |
3. | 1 30.4.2008 2008 40 1 95 17652 1 95 |
|-----------------------------------------------------------------------|
4. | 1 1.5.2008 2008 50 . 160 17653 2 160 |
5. | 1 2.5.2008 2008 50 . 160 17654 2 160 |
6. | 1 30.4.2009 2009 60 1 160 18017 2 160 |
|-----------------------------------------------------------------------|
7. | 2 1.1.2008 2008 26 . 96 17532 1 96 |
8. | 2 2.1.2008 2008 30 . 96 17533 1 96 |
9. | 2 30.4.2008 2008 40 1 96 17652 1 96 |
|-----------------------------------------------------------------------|
10. | 2 1.5.2008 2008 51 . 161 17653 2 161 |
11. | 2 2.5.2008 2008 50 . 161 17654 2 161 |
12. | 2 30.6.2009 2009 60 1 161 18078 2 161 |
+-----------------------------------------------------------------------+
发布于 2015-10-08 22:54:02
看起来您实际上是在尝试为id
和eventid
的独特组合创建总计,而不是id
和year
。根据您的示例,在计算期望的总和时,事件日期和“特殊日期”标志(event
)似乎并不重要。因此
bysort id eventid: egen _sum = total(var1)
或者更简单地说
egen _sum = total(var1) , by(id eventid)
应该都能给你想要的总数。关于
此外,我想说明缺失值,所以如果公司x的var1的所有值都是缺失变量,那么公司x和特定间隔的sum1必须包含缺失值,而不是0。
egen total()
上的missing
选项应该有助于解决此问题。
更新
不一定是对其他答案的改进,而是另一种方法(依赖于事件在原始数据中的正确顺序):
clear *
input id str10 date year var1 event DesiredSum
1 1.1.2008 2008 25 . 95
1 2.1.2008 2008 30 . 95
1 30.4.2008 2008 40 1 95
1 1.5.2008 2008 50 . 160
1 2.5.2008 2008 50 . 160
1 30.4.2009 2009 60 1 160
2 1.1.2008 2008 26 . 96
2 2.1.2008 2008 30 . 96
2 30.4.2008 2008 40 1 96
2 1.5.2008 2008 51 . 161
2 2.5.2008 2008 50 . 161
2 30.6.2009 2009 60 1 161
end
gen _obs = _n
gen date2 = daily(date, "DMY")
format date2 %td
bys id (_obs): gen eventid = sum(date2 == td(01jan2008)) + sum(event[_n-1] == 1)
egen sum = total(var1) , by(id eventid) missing
li , sepby(id eventid)
发布于 2015-10-08 23:47:46
如果您不反对将event
重新编码为更易于使用的代码,那么以下内容应该就足够了。在这里,我还假设event
用于标记事件发生的时间间隔的结束(我根据您的样本数据和我对这个问题的评论做出这个假设)。
clear *
input id str10 date year var1 event DesiredSum
1 1.1.2008 2008 25 . 95
1 2.1.2008 2008 30 . 95
1 31.4.2008 2008 40 1 95
1 1.5.2008 2008 50 . 160
1 2.5.2008 2008 50 . 160
1 31.4.2009 2009 60 1 160
2 1.1.2008 2008 26 . 96
2 2.1.2008 2008 30 . 96
2 31.6.2008 2008 40 1 96
2 1.5.2008 2008 51 . 161
2 2.5.2008 2008 50 . 161
2 31.6.2009 2009 60 1 161
end
bysort id : gen i = _n // to maintain sort order
/* This section of code changes event so that 1 indicates the start of the
interval. This data structure makes more sense to me */
replace event = 0 if mi(event)
replace event = 2 if event[_n-1] == 1 & _n != 1
replace event = event - 1 if event > 0
replace event = 1 in 1
gen event_id = event
replace event_id = event_id+event_id[_n-1] if i != 1
bysort id event_id : egen Sum = total(var1), missing
li id date event_id DesiredSum Sum, sepby(event_id)
当然,如果你不想改变event
,你可以用generate event2 = event
代替event
。
https://stackoverflow.com/questions/33018846
复制相似问题