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。所以这个想法是,无论年份如何,它只计算类别之间的转换次数。

我希望我的问题以清晰准确的方式提出。我不会轻视你花时间在这件事上,所以如果我能以任何方式改进我的问题,请说出来,我会尽我最大的努力完善我的问题,以免浪费你的时间。提前谢谢你。

I also asked the question on statalist

这是 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) 中创建的就业代码和当年的就业代码(始终是失业后的一年

)之间的交叉制表