Stata 中的 150x150 交叉表,显示类别之间的时间序列移动
150x150 crosstab in stata, showing timeseries movement between categories
我有点不知所措,我希望你能帮助我,或者至少给我指出正确的方向。
我得到了一个庞大的数据集(每年 5.8 次 mio 观察,超过 14 年),它处理个人随时间的职业。我需要总结一下这段时间的职业变化,这样我就可以看到人们在经历了一段失业期之后,从什么职业到什么职业,像这样:
但是,有 150 个类别,这意味着我无法让 stata 在没有换行的情况下显示整个交叉表。我需要以 .csv 或其他格式输出交叉表,以便之后在 GNU/R 中进一步操作。所以第一个问题是:
1) 如何将这种大小的交叉表提取到 csv/xls-file?
一种解决方案是以我可以将其导入 SPSS 的方式构建数据,SPSS 完全能够将如此巨大的交叉表输出到 excel-sheet.
现在,我的数据结构如下
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 2
2 2001 1
3 1999 1
3 2000 2
3 2001 2
4 1999 .
4 2000 1
4 2001 2
5 1999 1
5 2000 .
5 2001 2
end
list, sepby(id)
如您所见,这是一个长格式的简单数据框。我需要以这种方式构建数据,以便我可以创建一个交叉表来显示多年来的变化。例如。一个人可能在 1996 年被 "A" 占用,然后在 1997 年被 "B" 占用,然后在 1998 年又被 "A" 占用。这意味着这两年,他将被计算两次,因为他会从 A 到 B,然后从 B 到 A。所以这个想法是,无论年份如何,它只计算类别之间的转换次数。
我希望我的问题以清晰准确的方式提出。我不会轻视你花时间在这件事上,所以如果我能以任何方式改进我的问题,请说出来,我会尽我最大的努力完善我的问题,以免浪费你的时间。提前谢谢你。
这是 SPSS 中的解决方案。我假设您对记录缺失值之间的 switches/migrations 不感兴趣,但尽管有效职业代码之间存在缺失,但仍在考虑转换。
DATA LIST LIST /ID (F1.0) Year (F4.0) Code (A1).
BEGIN DATA.
1 1999 A
1 2000 A
1 2001 A
2 1999 A
2 2000 B
2 2001 A
3 1999 A
3 2000 B
3 2001 B
4 1999 .
4 2000 A
4 2001 B
5 1999 A
5 2000 A
5 2001 B
END DATA.
DATASET NAME DS0.
SORT CASES BY ID Year Code.
DO IF (ID=LAG(ID)).
IF (Code=".") Code=LAG(Code).
IF (Code<>LAG(Code) AND LAG(Code)<>".") SwitchInd=1.
END IF.
EXE.
SPLIT FILE SEPARATE BY ID.
CREATE SwitchNb=CSUM(SwitchInd).
SPLIT FILE OFF.
STRING SwitchFrom SwitchTo (A1).
DO IF (NVALID(SwitchInd)=1).
COMPUTE SwitchFrom=LAG(Code).
COMPUTE SwitchTo=Code.
END IF.
CTABLES /TABLE SwitchFrom[c] by SwitchTo[c] BY SwitchInd
/CATEGORIES VARIABLES = SwitchInd[1]
/CATEGORIES VARIABLES = ALL EMPTY=EXCLUDE
/TITLES CORNER="Migrations Analysis: From (Vertical) --> To (Horizontal)".
结果产生(来自 testforstackexhange.csv 中提供的演示数据):
A --> B: 4
B --> A: 1
来自 SSC 的 tabout
可能适合您:
clear
set more off
*----- example data set -----
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 2
2 2001 1
3 1999 1
3 2000 2
3 2001 2
4 1999 .
4 2000 1
4 2001 2
5 1999 1
5 2000 .
5 2001 2
end
list, sepby(id)
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
tabout fromoccup occup using tabtest.csv, replace cells(freq) format(0c)
我的计算中做了一些假设,但我的重点是table。参见 ssc describe tabout
。
你也可以考虑导出数据集本身。类似于:
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
collapse (count) counter=id, by(fromoccup occup)
dropmiss, obs any force
// pretty list
order fromoccup occup
sort fromoccup occup
list
相应地调整缺失。
编辑
既然您已经陈述了您的目标(邻接矩阵),就更容易提供精确的帮助。
下面将创建邻接矩阵并将其导出到 MS Excel。最后一个命令putexcel
需要Stata 13,如果没有可以导出之前创建的Stata数据集,和导出的矩阵差不多。
clear
set more off
*----- example data set -----
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 3
2 2001 1
3 1999 1
3 2000 3
3 2001 3
4 1999 .
4 2000 1
4 2001 3
5 1999 1
5 2000 .
5 2001 3
6 1999 4
6 2000 4
6 2001 3
end
list, sepby(id)
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
collapse (count) counter=id, by(fromoccup occup)
dropmiss, obs any force
// pretty list
order fromoccup occup
sort fromoccup occup
// add combinations with zero counts
fillin fromoccup occup
replace counter = 0 if _fillin
drop _fillin
// adjacency matrix
replace counter = counter > 0
reshape wide counter, i(fromoccup) j(occup)
rename counter* occup*
list
// put into matrix, adjust, and export
mkmat _all, matrix(adjmat)
unab coln : occup*
matrix t = . , adjmat[ 1... , "fromoccup"]'
matrix colnames t = fromoccup `coln'
matrix rownames t = r0
matrix a = t \ adjmat
matrix list a
putexcel B2=matrix(a) using adjtest.xls, replace
结果如下所示:
例如,作业流从 4 到 3,但从 3 到 4 没有。
这不是我自己的回答,而是 statalist.org 的 Klaudia Erhardt 给我的回答,我自己只做了轻微的优化。然而,这是最佳解决方案,所以这里是:
clear
input ///
id year occ_code unempl
1 1999 4 0
1 2000 4 0
1 2001 . 1
1 2002 . 1
1 2003 . 1
1 2004 5 0
1 2005 5 0
1 2006 5 0
1 2007 . 1
2 1999 . 1
2 2000 . 1
2 2001 . 1
2 2002 2 0
2 2003 2 0
2 2004 . 1
2 2005 2 0
2 2006 2 0
2 2007 . 1
3 1999 1 0
3 2000 1 0
3 2001 . 1
3 2002 1 0
3 2003 . 1
3 2004 2 0
3 2005 2 0
3 2006 3 0
3 2007 . 1
4 1999 1 0
4 2000 2 0
4 2001 3 0
4 2002 4 0
4 2003 . 1
4 2004 4 0
4 2005 3 0
4 2006 . 1
4 2007 3 0
end
sort id year
tsset id year
tsspell unempl if unempl==1 //tsspel is an SSC install
rename _seq temp
drop _end _spell
replace temp = temp[_n-1]+1 if unempl==1
by id: gen occ_prev = occ_code[_n-temp[_n-1]-1] if occ_code[_n-1]==. & occ_code != . // this is the trick!
drop temp
gen h1 = occ_prev
gen h2 = occ_code
tab2 occ_prev occ_code // this is to control if the data set shows the same
collapse (count) occ_prev occ_code, by(h2 h1)
keep if h1 != .
drop occ_prev
reshape wide occ_code, i(h1) j(h2)
recode _all (. = 0)
这有两件事:
1) 创建一个新变量,其就业代码不是来自前一年,而是来自某人受雇的最后一年。因此,有新工作的第一年会得到一个新变量,其中包含他上次工作时的工作代码。
2) 使用 collapse 创建一个 stata 数据集,该数据集实际上是在 1) 中创建的就业代码和当年的就业代码(始终是失业后的一年
)之间的交叉制表
我有点不知所措,我希望你能帮助我,或者至少给我指出正确的方向。
我得到了一个庞大的数据集(每年 5.8 次 mio 观察,超过 14 年),它处理个人随时间的职业。我需要总结一下这段时间的职业变化,这样我就可以看到人们在经历了一段失业期之后,从什么职业到什么职业,像这样:
但是,有 150 个类别,这意味着我无法让 stata 在没有换行的情况下显示整个交叉表。我需要以 .csv 或其他格式输出交叉表,以便之后在 GNU/R 中进一步操作。所以第一个问题是:
1) 如何将这种大小的交叉表提取到 csv/xls-file?
一种解决方案是以我可以将其导入 SPSS 的方式构建数据,SPSS 完全能够将如此巨大的交叉表输出到 excel-sheet.
现在,我的数据结构如下
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 2
2 2001 1
3 1999 1
3 2000 2
3 2001 2
4 1999 .
4 2000 1
4 2001 2
5 1999 1
5 2000 .
5 2001 2
end
list, sepby(id)
如您所见,这是一个长格式的简单数据框。我需要以这种方式构建数据,以便我可以创建一个交叉表来显示多年来的变化。例如。一个人可能在 1996 年被 "A" 占用,然后在 1997 年被 "B" 占用,然后在 1998 年又被 "A" 占用。这意味着这两年,他将被计算两次,因为他会从 A 到 B,然后从 B 到 A。所以这个想法是,无论年份如何,它只计算类别之间的转换次数。
我希望我的问题以清晰准确的方式提出。我不会轻视你花时间在这件事上,所以如果我能以任何方式改进我的问题,请说出来,我会尽我最大的努力完善我的问题,以免浪费你的时间。提前谢谢你。
这是 SPSS 中的解决方案。我假设您对记录缺失值之间的 switches/migrations 不感兴趣,但尽管有效职业代码之间存在缺失,但仍在考虑转换。
DATA LIST LIST /ID (F1.0) Year (F4.0) Code (A1).
BEGIN DATA.
1 1999 A
1 2000 A
1 2001 A
2 1999 A
2 2000 B
2 2001 A
3 1999 A
3 2000 B
3 2001 B
4 1999 .
4 2000 A
4 2001 B
5 1999 A
5 2000 A
5 2001 B
END DATA.
DATASET NAME DS0.
SORT CASES BY ID Year Code.
DO IF (ID=LAG(ID)).
IF (Code=".") Code=LAG(Code).
IF (Code<>LAG(Code) AND LAG(Code)<>".") SwitchInd=1.
END IF.
EXE.
SPLIT FILE SEPARATE BY ID.
CREATE SwitchNb=CSUM(SwitchInd).
SPLIT FILE OFF.
STRING SwitchFrom SwitchTo (A1).
DO IF (NVALID(SwitchInd)=1).
COMPUTE SwitchFrom=LAG(Code).
COMPUTE SwitchTo=Code.
END IF.
CTABLES /TABLE SwitchFrom[c] by SwitchTo[c] BY SwitchInd
/CATEGORIES VARIABLES = SwitchInd[1]
/CATEGORIES VARIABLES = ALL EMPTY=EXCLUDE
/TITLES CORNER="Migrations Analysis: From (Vertical) --> To (Horizontal)".
结果产生(来自 testforstackexhange.csv 中提供的演示数据):
A --> B: 4
B --> A: 1
tabout
可能适合您:
clear
set more off
*----- example data set -----
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 2
2 2001 1
3 1999 1
3 2000 2
3 2001 2
4 1999 .
4 2000 1
4 2001 2
5 1999 1
5 2000 .
5 2001 2
end
list, sepby(id)
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
tabout fromoccup occup using tabtest.csv, replace cells(freq) format(0c)
我的计算中做了一些假设,但我的重点是table。参见 ssc describe tabout
。
你也可以考虑导出数据集本身。类似于:
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
collapse (count) counter=id, by(fromoccup occup)
dropmiss, obs any force
// pretty list
order fromoccup occup
sort fromoccup occup
list
相应地调整缺失。
编辑
既然您已经陈述了您的目标(邻接矩阵),就更容易提供精确的帮助。
下面将创建邻接矩阵并将其导出到 MS Excel。最后一个命令putexcel
需要Stata 13,如果没有可以导出之前创建的Stata数据集,和导出的矩阵差不多。
clear
set more off
*----- example data set -----
input ///
id year occup
1 1999 1
1 2000 1
1 2001 1
2 1999 1
2 2000 3
2 2001 1
3 1999 1
3 2000 3
3 2001 3
4 1999 .
4 2000 1
4 2001 3
5 1999 1
5 2000 .
5 2001 3
6 1999 4
6 2000 4
6 2001 3
end
list, sepby(id)
*----- what you want -----
bysort id (year): gen fromoccup = occup[_n-1]
collapse (count) counter=id, by(fromoccup occup)
dropmiss, obs any force
// pretty list
order fromoccup occup
sort fromoccup occup
// add combinations with zero counts
fillin fromoccup occup
replace counter = 0 if _fillin
drop _fillin
// adjacency matrix
replace counter = counter > 0
reshape wide counter, i(fromoccup) j(occup)
rename counter* occup*
list
// put into matrix, adjust, and export
mkmat _all, matrix(adjmat)
unab coln : occup*
matrix t = . , adjmat[ 1... , "fromoccup"]'
matrix colnames t = fromoccup `coln'
matrix rownames t = r0
matrix a = t \ adjmat
matrix list a
putexcel B2=matrix(a) using adjtest.xls, replace
结果如下所示:
例如,作业流从 4 到 3,但从 3 到 4 没有。
这不是我自己的回答,而是 statalist.org 的 Klaudia Erhardt 给我的回答,我自己只做了轻微的优化。然而,这是最佳解决方案,所以这里是:
clear
input ///
id year occ_code unempl
1 1999 4 0
1 2000 4 0
1 2001 . 1
1 2002 . 1
1 2003 . 1
1 2004 5 0
1 2005 5 0
1 2006 5 0
1 2007 . 1
2 1999 . 1
2 2000 . 1
2 2001 . 1
2 2002 2 0
2 2003 2 0
2 2004 . 1
2 2005 2 0
2 2006 2 0
2 2007 . 1
3 1999 1 0
3 2000 1 0
3 2001 . 1
3 2002 1 0
3 2003 . 1
3 2004 2 0
3 2005 2 0
3 2006 3 0
3 2007 . 1
4 1999 1 0
4 2000 2 0
4 2001 3 0
4 2002 4 0
4 2003 . 1
4 2004 4 0
4 2005 3 0
4 2006 . 1
4 2007 3 0
end
sort id year
tsset id year
tsspell unempl if unempl==1 //tsspel is an SSC install
rename _seq temp
drop _end _spell
replace temp = temp[_n-1]+1 if unempl==1
by id: gen occ_prev = occ_code[_n-temp[_n-1]-1] if occ_code[_n-1]==. & occ_code != . // this is the trick!
drop temp
gen h1 = occ_prev
gen h2 = occ_code
tab2 occ_prev occ_code // this is to control if the data set shows the same
collapse (count) occ_prev occ_code, by(h2 h1)
keep if h1 != .
drop occ_prev
reshape wide occ_code, i(h1) j(h2)
recode _all (. = 0)
这有两件事:
1) 创建一个新变量,其就业代码不是来自前一年,而是来自某人受雇的最后一年。因此,有新工作的第一年会得到一个新变量,其中包含他上次工作时的工作代码。 2) 使用 collapse 创建一个 stata 数据集,该数据集实际上是在 1) 中创建的就业代码和当年的就业代码(始终是失业后的一年
)之间的交叉制表