我有以下数据
id pair_id id_in id_out date
1 1 2 3 1/1/2010
2 1 2 3 1/2/2010
3 1 3 2 1/3/2010
4 1 3 2 1/5/2010
5 1 3 2 1/7/2010
6 2 2 1 1/2/2010
7 3 1 3 1/5/2010
8 2 1 2 1/7/2010
在任何给定的一行,我想知道从id_in
角度看唯一对id_out
和id_in
之间的流入/流出差异
例如,对于id_in == 2
和id_out == 3
,它看起来如下(从id_in == 2
的角度来看)
id pair_id id_in id_out date inflow_outflow
1 1 2 3 1/1/2010 1
2 1 2 3 1/2/2010 2
3 1 3 2 1/3/2010 1
4 1 3 2 1/5/2010 0
5 1 3 2 1/7/2010 -1
解释。首先收到id_in == 2
,然后他们获得+1
,然后他们再次收到+2
。然后他们放弃了所以它被-1
缩小,使总数达到1
等等。
这就是我试过的
sort pair_id id_in date
gen count = 0
qui forval i = 2/`=_N' {
local I = `i' - 1
count if id_in == id_out[`i'] in 1/`I'
replace count = r(N) in `i'
}
答案 0 :(得分:0)
我没有遵循这里的所有逻辑,特别是从一个成员的角度来呈现交易似乎很随意。但是来自松散相似问题的广泛印象是你不应该在这里考虑循环。使用by:
和累计金额就足够了。有人试图在http://www.stata-journal.com/sjpdf.html?articlenum=dm0043处理如何处理对偶的系统讨论,但这只是一个开始。
请注意,根据某种显示格式显示日期是一个很小的痛苦,因为它们需要进行逆向工程。来自SSC的dataex
可用于创建易于复制和粘贴的示例。
此代码可能会提示一些技巧:
clear
input id pair_id id_in id_out str8 sdate
1 1 2 3 "1/1/2010"
2 1 2 3 "1/2/2010"
3 1 3 2 "1/3/2010"
4 1 3 2 "1/5/2010"
5 1 3 2 "1/7/2010"
6 2 2 1 "1/2/2010"
7 3 1 3 "1/5/2010"
8 2 1 2 "1/7/2010"
end
gen date = daily(sdate, "MDY")
format date %td
assert id_in != id_out
gen pair1 = cond(id_in < id_out, id_in, id_out)
gen pair2 = cond(id_in < id_out, id_out, id_in)
bysort pair_id (date): gen sum1 = sum(id_in == pair1) - sum(id_out == pair1)
bysort pair_id (date): gen sum2 = sum(id_in == pair2) - sum(id_out == pair2)
list date id_* pair? sum?, sepby(pair_id)
+----------------------------------------------------------+
| date id_in id_out pair1 pair2 sum1 sum2 |
|----------------------------------------------------------|
1. | 01jan2010 2 3 2 3 1 -1 |
2. | 02jan2010 2 3 2 3 2 -2 |
3. | 03jan2010 3 2 2 3 1 -1 |
4. | 05jan2010 3 2 2 3 0 0 |
5. | 07jan2010 3 2 2 3 -1 1 |
|----------------------------------------------------------|
6. | 02jan2010 2 1 1 2 -1 1 |
7. | 07jan2010 1 2 1 2 0 0 |
|----------------------------------------------------------|
8. | 05jan2010 1 3 1 3 1 -1 |
+----------------------------------------------------------+
答案 1 :(得分:0)
特定对(由pair_id
定义)始终由两个实体组成,这两个实体可以以两种方式之一进行排序。例如,实体5与实体8,实体8与实体5.如果一个正在接收,另一个正在发出,必然。
可以在下面找到两种略有不同的解决问题的方法。
clear all
set more off
*----- example data -----
input id pair_id id_in id_out str8 sdate
1 1 2 3 "1/1/2010"
2 1 2 3 "1/2/2010"
3 1 3 2 "1/3/2010"
4 1 3 2 "1/5/2010"
5 1 3 2 "1/7/2010"
6 2 2 1 "1/2/2010"
7 3 1 3 "1/5/2010"
8 2 1 2 "1/7/2010"
end
gen date = daily(sdate, "MDY")
format date %td
drop sdate
sort pair_id date id
list, sepby(pair_id)
*---- what you want -----
// approach 1
bysort pair_id (date id) : gen sum1 = sum(cond(id_in == id_in[1], 1, -1))
gen sum2 = -1 * sum1
// approach 2
bysort pair_id (id_in date id) : gen temp = cond(id_in == id_in[1], 1, -1)
bysort pair_id (date id) : gen sum100 = sum(temp)
gen sum200 = -1 * sum100
// list
drop temp
sort pair_id date
list, sepby(pair_id)
第一种方法涉及创建一个变量,该变量保存根据date
变量首先接收的实体的差异。 sum1
就是这么做的。变量sum2
保存另一个实体的差异。
第二种方法创建一个变量,用于保存具有最小识别号的实体的差异。我把它命名为sum100
。变量sum200
保存另一个实体的信息。
请注意,如果id
无法唯一标识观察结果,我会将pair_id date
添加到排序列表中。
第二种方法相当于@NickCox提供的代码,或者我相信。
结果:
. list, sepby(pair_id)
+---------------------------------------------------------------------------+
| id pair_id id_in id_out date sum1 sum2 sum100 sum200 |
|---------------------------------------------------------------------------|
1. | 1 1 2 3 01jan2010 1 -1 1 -1 |
2. | 2 1 2 3 02jan2010 2 -2 2 -2 |
3. | 3 1 3 2 03jan2010 1 -1 1 -1 |
4. | 4 1 3 2 05jan2010 0 0 0 0 |
5. | 5 1 3 2 07jan2010 -1 1 -1 1 |
|---------------------------------------------------------------------------|
6. | 6 2 2 1 02jan2010 1 -1 -1 1 |
7. | 8 2 1 2 07jan2010 0 0 0 0 |
|---------------------------------------------------------------------------|
8. | 7 3 1 3 05jan2010 1 -1 1 -1 |
+---------------------------------------------------------------------------+
仔细检查它们,因为两种方法之间的差异是微妙的,至少在最初阶段。