Inflow/Outflow 在 Stata 中计数
Inflow/Outflow Count in Stata
我有以下数据
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_in
和 id_out
之间的 inflow/outflow 差异是什么
例如,对于 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'
}
我没有遵循这里的所有逻辑,特别是从一个成员的角度呈现交易似乎很武断。但是从松散相似的问题中得出的一个普遍印象是,您不应该在这里考虑循环。使用 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 |
+----------------------------------------------------------+
特定对(由 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 |
+---------------------------------------------------------------------------+
仔细检查它们,因为这两种方法之间的区别很细微,至少在最初是这样。
我有以下数据
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_in
和 id_out
之间的 inflow/outflow 差异是什么
例如,对于 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'
}
我没有遵循这里的所有逻辑,特别是从一个成员的角度呈现交易似乎很武断。但是从松散相似的问题中得出的一个普遍印象是,您不应该在这里考虑循环。使用 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 |
+----------------------------------------------------------+
特定对(由 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 |
+---------------------------------------------------------------------------+
仔细检查它们,因为这两种方法之间的区别很细微,至少在最初是这样。