首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Stata:按特定日期范围生成sum / total并将其保存为新变量

Stata:按特定日期范围生成sum / total并将其保存为新变量
EN

Stack Overflow用户
提问于 2015-10-08 22:35:51
回答 3查看 10.7K关注 0票数 3

我使用的面板数据包含几家公司(id),涵盖了从2008年1月1日到2013年1月1日(dateyear)这段时间。我想生成新的变量(sum1),其中包含每个公司和特定时间间隔的var1的每日观察总和。如果间隔等于每一年,我将使用函数total()

代码语言:javascript
运行
复制
 bysort id year: egen sum1=total(var1)

然而,在我的例子中,时间间隔被确定为两个事件之间的间隔。我有一个名为event的特殊变量,如果事件在特殊日期发生,则该变量的值为1,否则该变量将丢失。每个公司都有5到10个活动。事件之间的间隔不相等;因此第一个间隔可以包含60个观察值,下一个间隔包含360个观察值。对于不同的公司,间隔也不相等。每个公司的第一个间隔的开始日期是1.1.2008。第二个间隔的开始日期是第一个事件的日期+1天。此外,我还想说明缺失值,因此如果公司x的var1的所有值都是缺失变量,那么公司x和特定间隔的sum1必须包含缺失值,而不是0。

我的面板看起来像这样:

代码语言:javascript
运行
复制
   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  

我试着写不同的循环(whileif),但是我做得不对。我不能使用rolling,因为我的间隔不一样。

我的另一个想法是首先创建组标识符(称为event_id),它包含每个间隔和每个公司的event_id。然后我可以使用bysort id event_id: egen sum1=total(var1),但不幸的是我不知道如何做到这一点。因此,我的面板中的变量event_idsum1并不存在,并且作为我想要实现的输出的示例。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-10-09 00:16:34

通过以下更改,我可以理解该示例:

4月31日和6月31日的

  1. 日期是1天前的打字错误。然而,
  2. Date 31.6.2008应该是30.4.2008。

也就是说,一个倒转时间的技巧使得细分成咒语变得很容易。给定每个咒语的ends的标记1,我们就可以使用sum()向后累积。这里关键的小细节是sum()忽略缺少的值,或者更准确地说,将它们视为零。在这里,这完全是一个特性,尽管不完全是OP在应用egen, total()时想要的。

然后反转拼写编号,将时间反转到正常方向,并像在其他答案中一样应用egen。Reversing和reversing back都是使用-进行的否定。在面板中对日期进行排序只是表面上的,一旦我们有了咒语的划分,但仍然是正确的事情。

有关Stata中的法术的更多信息,请参阅here

关于如何使用dataex (SSC)提供数据示例的Statalist的提示,也适用于这里,只需稍作修改,请参阅here

代码语言:javascript
运行
复制
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 |
     +-----------------------------------------------------------------------+
票数 3
EN

Stack Overflow用户

发布于 2015-10-08 22:54:02

看起来您实际上是在尝试为ideventid的独特组合创建总计,而不是idyear。根据您的示例,在计算期望的总和时,事件日期和“特殊日期”标志(event)似乎并不重要。因此

代码语言:javascript
运行
复制
bysort id eventid: egen _sum = total(var1)

或者更简单地说

代码语言:javascript
运行
复制
egen _sum = total(var1) , by(id eventid)

应该都能给你想要的总数。关于

此外,我想说明缺失值,所以如果公司x的var1的所有值都是缺失变量,那么公司x和特定间隔的sum1必须包含缺失值,而不是0。

egen total()上的missing选项应该有助于解决此问题。

更新

不一定是对其他答案的改进,而是另一种方法(依赖于事件在原始数据中的正确顺序):

代码语言:javascript
运行
复制
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)
票数 2
EN

Stack Overflow用户

发布于 2015-10-08 23:47:46

如果您不反对将event重新编码为更易于使用的代码,那么以下内容应该就足够了。在这里,我还假设event用于标记事件发生的时间间隔的结束(我根据您的样本数据和我对这个问题的评论做出这个假设)。

代码语言:javascript
运行
复制
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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33018846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档