reshape.ado

来自「是一个经济学管理应用软件 很难找的 但是经济学学生又必须用到」· ADO 代码 · 共 1,461 行 · 第 1/2 页

ADO
1,461
字号
*! version 4.1.6  12nov2003
program define reshape
	version 5.0, missing

	if "`1'"=="clear" {
		char _dta[ReS_ver]
		char _dta[ReS_i]
		char _dta[ReS_j]
		char _dta[ReS_jv]
		char _dta[ReS_Xij]
		char _dta[Res_Xi]
		char _dta[ReS_atwl]
		char _dta[ReS_str]
		exit
	}

	if "`1'"=="wide" | "`1'"=="long" {
		DoNew `*'
		exit
	}

	local syntax : char _dta[ReS_ver]

	if "`1'"=="" | "`1'"==substr("query",1,length("`1'")) {
		if "`syntax'"=="" | "`syntax'"=="v.2" {
			Query
			exit
		}
		local 1 "query"
	}

	if "`syntax'"=="" {
		IfOld `1'
		if `s(oldflag)' {
			DoOld `*'
			char _dta[ReS_ver] "v.1"
		}
		else {
			DoNew `*'
			char _dta[ReS_ver] "v.2"
		}
		exit
	}

	if "`syntax'"=="v.1" {
		DoOld `*'
	}
	else 	DoNew `*'
end

program define IfOld, sclass
	if "`1'"=="" {
		sret local oldflag 0
		exit
	}
	local l = length("`1'")
	if "`1'"==substr("groups",1,`l') | /*
	*/ "`1'"==substr("vars",1,`l') | /*
	*/ "`1'"==substr("cons",1,`l') | /*
	*/ "`1'"==substr("query",1,`l') {
		sret local oldflag 1
		exit
	}
	sret local oldflag 0
end

program define IfNew, sclass
	if "`1'"=="i" | "`1'"=="j" | "`1'"=="xij" | "`1'"=="xi" | /*
	*/ "`1'"=="error" {
		sret local newflag 1
	}
	else	sret local newflag 0
end

program define DoNew
	local c "`1'"
	mac shift

	if "`c'"=="i" {
		if "`*'" == "" { error 198 }
		unabbrev `*', max(10) min(1)
		char _dta[ReS_i] "`s(varlist)'"
		exit
	}


	if "`c'"=="j" {
		J `*'
		exit
	}

	if "`c'"=="xij" {
		Xij `*'
		exit
	}

	if "`c'"=="xi" {
		sret clear
		if "`*'"!="" {
			unabbrev `*'
		}
		char _dta[Res_Xi] "`s(varlist)'"
		exit
	}

	if "`c'"=="" {				/* reshape 		*/
		Query
		exit
	}

	if "`c'"=="long" {			/* reshape long		*/
		if "`1'" != "" {
			Simple long `*'
		}
		capture noisily Long `*'
		Macdrop
		exit _rc
	}


	if "`c'"=="wide" {			/* reshape wide		*/
		if "`1'" != "" {
			Simple wide `*'
		}
		capture noisily Wide `*'
		Macdrop
		exit _rc
	}

	if "`c'"==substr("error",1,max(3,length("`c'"))) {
		capture noisily Qerror `*'
		Macdrop
		exit
	}

	IfOld `c'
	if `s(oldflag)' {
		di in red "may not mix old and new syntax;"
		di in red "either use new syntax or " /*
		*/ _quote "reshape clear" _quote /*
		*/ " and start over using old syntax."
		exit 198
	}
	error 198
end

program define Macdrop
	mac drop ReS_j ReS_jv ReS_i ReS_Xij rVANS Res_Xi /*
	*/ ReS_atwl ReS_str S_1 S_2
end

program define ReportL /* old_obs old_vars */
	Report1 `1' `2' wide long

	local n : word count $ReS_jv
	di in gr "j variable (`n' values)" _col(43) "->" _col(48) /*
	*/ in ye "$ReS_j"
	di in gr "xij variables:"
	parse "$ReS_Xij", parse(" ")
	while "`1'"!="" {
		RepF "`1'"
		local skip = 39 - length("$S_1")
		di in ye _skip(`skip') "$S_1" _col(43) in gr "->" /*
		*/ in ye _col(48) "$S_2"
		mac shift
	}
	di in smcl in gr "{hline 77}"
end

program define RepF /* element from ReS_Xij */
	local v "`1'"
	if "$ReS_jv2" != "" {
		local n : word count $ReS_jv2
		parse "$ReS_jv2", parse(" ")
	}
	else {
		local n : word count $ReS_jv
		parse "$ReS_jv", parse(" ")
	}
	if `n'>=1 {
		Subname `v' `1'
		local list $S_1
	}
	if `n'>=2 {
		Subname `v' `2'
		local list `list' $S_1
	}
	if `n'==3 {
		Subname `v' ``n''
		local list `list' $S_1
	}
	else if `n'>3 {
		Subname `v' ``n''
		local list `list' ... $S_1
	}
	Subname `v' $ReS_atwl
	global S_2 $S_1
	global S_1 `list'
end


program define Report1 /* <#oobs> <#ovars> {wide|long} {long|wide} */
	local oobs "`1'"
	local ovars "`2'"
	local wide "`3'"
	local long "`4'"

	di in smcl _n in gr /*
	*/ "Data" _col(36) "`wide'" _col(43) "->" _col(48) "`long'" /*
	*/ _n "{hline 77}"

	di in gr "Number of obs." _col(32) in ye %8.0g `oobs' /*
	*/ in gr _col(43) "->" in ye %8.0g _N

	quietly desc, short

	di in gr "Number of variables" _col(32) in ye %8.0g `ovars' /*
	*/ in gr _col(43) "->" in ye %8.0g r(k)
end

program define ReportW /* old_obs old_vars */
	Report1 `1' `2' long wide

	local n : word count $ReS_jv2
	local col = 31+(9-length("$ReS_j"))
	di in gr "j variable (`n' values)" /*
		*/ _col(`col') in ye "$ReS_j" in gr _col(43) "->" /*
		*/ _col(48) "(dropped)"
	di in gr "xij variables:"
	parse "$ReS_Xij", parse(" ")
	while "`1'"!="" {
		RepF "`1'"
		local skip = 39 - length("$S_2")
		di in ye _skip(`skip') "$S_2" _col(43) in gr "->" /*
		*/ in ye _col(48) "$S_1"
		mac shift
	}
	di in smcl in gr "{hline 77}"
end





program define Simple /* {wide|long} <funnylist>, i(varlist)
					[j(varname [values])] */
	local cmd "`1'"
	mac shift
	parse "`*'", parse(" ,")
	while "`1'"!="" & "`1'"!="," {
		local list `list' `1'
		mac shift
	}
	if "`list'"=="" {
		error 198
	}
	if "`1'" != "," {
		di in red "option i() required"
		exit 198
	}
	local options "I(string) J(string) ATwl(string) String"
	parse "`*'"
	if "`i'"=="" {
		di in red "option i() required"
		exit 198
	}
	unabbrev `i'
	local i "`s(varlist)'"

	if "`j'" != "" {
		parse "`j'", parse(" ")
		local jvar "`1'"
		mac shift
		local jvals "`*'"
	}
	else 	local jvar "_j"

	if "`cmd'"=="wide" {
		/* When reshaping wide we can -unab- the variable list */
		capture unab list : `list' /* ignore _rc, error caught later */
		/* When reshaping wide we can -unab- the j variable */
		capture unab jvar : `jvar' /* use -unab- not -ConfVar- here */
/*  old code
		capture ConfVar `jvar'
*/
		if _rc {
			if _rc==111 {
				di in red "`jvar' not found -- " _c
				if "`jvar'"=="_j" {
					di in red "specify j() option"
				}
				else	di in red "data already wide"
				exit 111
			}
			ConfVar `jvar'
			exit 198	/* just in case */
		}
	}
	else {
		capture confirm new var `jvar'
		if _rc {
			if _rc==110 {
				di in red /*
			*/ "`jvar' already defined -- data already long"
				exit 110
			}
			confirm new var `jvar'
			exit 198	/* just in case */
		}
	}

	if "`atwl'"!="" {
		local atwl "atwl(`atwl')"
	}
	if "`string'" != "" {
		local string ", string"
	}


	reshape clear
	reshape i `i'
	reshape j `jvar' `jvals' `string'
	reshape xij `list' `atwl'
end

program define Xij /* <names-maybe-with-@>[, atwl(string) */
	if "`*'"=="" { error 198 }
	parse "`*'", parse(" ,")
	while "`1'" != "" & "`1'"!="," {
		local list "`list' `1'"
		mac shift
	}
	if "`list'"=="" {
		error 198
	}
	local list `list'
	if "`1'"=="," {
		local options "ATwl(string)"
		parse "`*'"
	}
	char _dta[ReS_Xij] "`list'"
	char _dta[ReS_atwl] "`atwl'"
end

program define DoOld
	local c "`1'"
	local l = length("`c'")
	mac shift

	if "`c'"==substr("groups",1,`l') {
		if "`2'" == "" {
			error 198
		}
		DoNew j `*'
		exit
	}
	if "`c'"==substr("vars",1,`l') {
		DoNew xij `*'
		exit
	}
	if "`c'"==substr("cons",1,`l') {
		DoNew i `*'
		exit
	}
	if "`c'"==substr("query",1,`l') {
		local cons   : char _dta[ReS_i]
		local grpvar : char _dta[ReS_j]
		local values : char _dta[ReS_jv]
		local vars   : char _dta[ReS_Xij]
		local car    : char _dta[Res_Xi]
		di "group var:  `grpvar'"
		di "values:     `values'"
		di "cons:       `cons'"
		di "vars:       `vars'"
		exit
	}
	if "`c'"=="wide" {
		DoNew wide `*'
		exit
	}
	if "`c'"=="long" {
		DoNew long `*'
		exit
	}
	IfNew `c'
	if `s(newflag)' {
		di in red "may not mix old and new syntax;"
		di in red "either use old syntax or " /*
		*/ _quote "reshape clear" _quote /*
		*/ " and start over using new syntax."
		exit 198
	}
	error 198
end



program define Query
	if "`*'"!="" {
		error 198
	}
	local cons   : char _dta[ReS_i]
	local grpvar : char _dta[ReS_j]
	local values : char _dta[ReS_jv]
	local vars   : char _dta[ReS_Xij]
	local car    : char _dta[Res_Xi]
	local atwl   : char _dta[ReS_atwl]
	local isstr  : char _dta[ReS_str]

	if "`grpvar'"!="" {
		capture ConfVar `grpvar'
		if _rc {
			di _n in ye " (data is wide)"
		}
		else	di _n in ye " (data is long)"
	}
	else	di

	if "`cons'"=="" {
		local ccons "in gr"
		local cons "<varlist>"
	}

	if "`grpvar'"=="" {
		local cgrpvar "in gr"
		local grpvar "<varname>"
		if "`values'"=="" {
			local values "[<#> - <#>]"
		}
	}
	else if `isstr' {
		local values "`values', string"
	}

	if "`vars'"=="" {
		local cvars "in gr"
		local vars "<varnames-without-#j-suffix>"
	}
	else {
		if "`atwl'" != "" {
			local vars "`vars', atwl(`atwl')"
		}
	}
	if "`car'"=="" {
		local ccar "in gr"
		local car "<varlist>"
	}

	di in smcl in gr "{c TLC}{hline 30}{c TT}{hline 46}{c TRC}" _n /*
	*/ "{c |} Xij" _col(32) "{c |} Command/contents" _col(79) "{c |}" _n /*
	*/ in gr "{c LT}{hline 30}{c +}{hline 46}{c RT}"

	di in smcl in gr /*
	*/ "{c |} Subscript i,j definitions:" _col(32) "{c |}" _col(79) "{c |}"

	di in smcl in gr /*
	*/ "{c |}  group id variable(s)" _col(32) "{c |} reshape i " _c
	Qlist 44 "`ccons'" `cons'

	di in smcl in gr /*
	*/ "{c |}  within-group variable" _col(32) "{c |} reshape j " _c

	Qlist 44 "`cgrpvar'" `grpvar' `values'
	di in smcl in gr /*
	*/ "{c |}   and its range" _col(32) "{c |}" _col(79) "{c |}"

	di in smcl in gr "{c |}" _col(32) "{c |}" _col(79) "{c |}"

	di in smcl in gr /*
	*/ "{c |} Variable X definitions:" _col(32) "{c |}" _col(79) "{c |}"

	di in smcl in gr /*
	*/ "{c |}  varying within group" _col(32) "{c |} reshape xij " _c
	Qlist 46 "`cvars'" `vars'

	di in smcl in gr /*
	*/ "{c |}  constant within group (opt) {c |} reshape xi  " _c
	Qlist 46 "`ccar'" `car'

	di in smcl in gr "{c BLC}{hline 30}{c BT}{hline 46}{c BRC}"

	local cons   : char _dta[ReS_i]
	local grpvar : char _dta[ReS_j]
	local values : char _dta[ReS_jv]
	local vars   : char _dta[ReS_Xij]
	local car    : char _dta[Res_Xi]

	if "`cons'"=="" {
		di in gr "First type " _quote in white /*
		*/ "reshape i" in gr _quote /*
		*/ " to define the i variable."
		exit
	}
	if "`grpvar'"=="" {
		di in gr "Type " _quote in wh /*
		*/ "reshape j" in gr _quote /*
		*/ " to define the j variable and, optionally, values."
		exit
	}
	if "`vars'"=="" {
		di in gr "Type " _quote in wh /*
		*/ "reshape xij" in gr _quote /*
		*/ " to define variables that vary within i."
		exit
	}
	if "`car'"=="" {
		di in gr /*
	*/ "Optionally type " _quote in wh "reshape xi" in gr _quote /*
	*/ " to define variables that are constant within i."
	}
	capture ConfVar `grpvar'
	if _rc {
		di in gr "Type " _quote in wh "reshape long" in gr _quote /*
		*/ " to convert the data to long form."
		exit
	}
	di in gr "Type " _quote in wh "reshape wide" in gr _quote /*
		*/ " to convert the data to wide form."
end

program define Qlist /* col <optcolor> stuff */
	local col `1'
	local clr "`2'"
	mac shift 2
	while "`1'" != "" {
		local l = length("`1'")
		if `col' + `l' + 1 >= 79 {
			local skip = 79 - `col'
			di in smcl in gr _skip(`skip') "{c |}" _n /*
			*/ "{c |}" _col(32) "{c |} " _c
			local col 34
		}
		di in ye `clr' "`1' " _c
		local col = `col' + `l' + 1
		mac shift
	}
	local skip = 79 - `col'
	di in smcl in gr _skip(`skip') "{c |}"
end

program define Qerror
	Macros
	Macros2 preserve
	capture ConfVar $ReS_j
	if _rc==0 {
		QerrorW
	}
	else	QerrorL
end


/* ------------------------------------------------------------------------ */
program define Wide		/* reshape wide */
	local oldobs = _N
	quietly describe, short
	local oldvars = r(k)

	Macros
	capture ConfVar $ReS_j
	if _rc {
		di in blu "(already wide)"
		exit
	}
	ConfVar $ReS_j
	confirm var $ReS_j $rVANS $ReS_i $Res_Xi
	capture ConfVar _merge
	if _rc ==0 {
		di in red "cannot convert data containing variable _merge;"
		di in red "drop or rename _merge"
		exit 110
	}

	preserve
	Macros2
	if $S_1 {
		restore, preserve
	}
	ConfVar $ReS_j
	confirm var $ReS_j $Res_Xi

	Veruniq

/*
	Organization:
		dataset dscons:		(may not exist)
			$ReS_i		(1 obs per $ReS_i)
			$Res_Xi

		dataset dsvars:
			$ReS_i		(many obs per $ReS_i)
			$ReS_j
			$ReS_Xij

		dataset dsnew:
			$ReS_i		(1 obs per $ReS_i)
			<widened $VARS>
			<$Res_Xi>

	Note, ("`dscons'"!="") == ("$ReS_i"!="")
*/

	tempfile dsnew dsvars hold
	if "$Res_Xi" != "" {
		tempfile dscons
	}
	quietly {
		keep $ReS_j $rVANS $ReS_i $Res_Xi
		sort $ReS_i $ReS_j
		if "`dscons'"!="" {
			save "`dscons'", replace    /* temporarily */
			drop $Res_Xi
			save "`dsvars'", replace
			use "`dscons'", clear
		}
		else	save "`dsvars'", replace

		by $ReS_i: keep if _n==1
		if "`dscons'"!="" {
			keep $ReS_i $Res_Xi
			save "`dscons'", replace
		}
		keep $ReS_i
		save "`dsnew'", replace

	/* datasets initialized, now step through each value: */

		globa ReS_jv2
		parse "$ReS_jv", parse(" ")
		while "`1'" != "" {
			use "`dsvars'", clear
			if $ReS_str {
				keep if $ReS_j=="`1'"
			}
			else 	keep if $ReS_j == `1'
			if _N==0 {
				noi di in bl /*
				*/ "(note: no data for $ReS_j == `1')"
				capture use "`dsnew'", replace
			}
			else {
				global ReS_jv2 $ReS_jv2 `1'
				drop $ReS_j
				noisily Widefix `1'
				save "`hold'", replace
				use "`dsnew'", clear
				merge $ReS_i using "`hold'"
				drop _merge
				sort $ReS_i
				save "`dsnew'", replace
			}
			mac shift
		}
		if "`dscons'" != "" {
			merge $ReS_i using "`dscons'"
			drop _merge
		}
	}
	global S_FN
	global S_FNDATE
	if "`syntax'" != "v.1" {
		sort $ReS_i
	}
	restore, not

	local syntax: char _dta[ReS_ver]
	if "`syntax'" != "v.1" {
		ReportW `oldobs' `oldvars'
	}
end

program define Veruniq
	sort $ReS_i $ReS_j
	capture by $ReS_i $ReS_j: assert _N==1
	if _rc {
		di in red "$ReS_j not unique within $ReS_i;"
		di in red /*
		*/ "there are multiple observations at the same $ReS_j" /*
		*/ " within $ReS_i."
		di in red "Type " _quote "reshape error" _quote /*
		*/ " for a listing of the problem observations."
		exit 9
	}
	if "$Res_Xi"=="" {
		exit
	}
	sort $ReS_i $Res_Xi $ReS_j
	tempvar cnt1 cnt2
	quietly by $ReS_i: gen long `cnt1' = _N
	quietly by $ReS_i $Res_Xi: gen long `cnt2' = _N
	capture assert `cnt1' == `cnt2'
	if _rc==0 {
		exit
	}
	parse "$Res_Xi", parse(" ")
	while "`1'"!=""  {
		capture by $ReS_i: assert `1'==`1'[1]
		if _rc {
			di in red "`1' not constant within $ReS_i"
		}
		mac shift
	}
	di in red "Type " _quote "reshape error" _quote /*
		*/ " for a listing of the problem observations."
	exit 9
end

program define QerrorW
	ConfVar $ReS_j
	confirm var $ReS_j $ReS_Xij $ReS_i $Res_Xi
	sort $ReS_i $ReS_j
	capture by $ReS_i $ReS_j: assert _N==1
	if _rc {
		Msg1
		di in gr /*
	*/ "The data are in the long form;  j should be unique within i." _n
		di in gr /*
		*/ "There are multiple observations on the same " /*
		*/ in ye "$ReS_j" in gr " within " /*
		*/ in ye "$ReS_i" in gr "." _n

		tempvar bad
		quietly by $ReS_i $ReS_j: gen `bad' = _N!=1
		quietly count if `bad'
		di in gr /*
		*/ "The following " r(N) /*
		*/ " out of " _N /*
		*/ " observations have repeated $ReS_j values:"
		list $ReS_i $ReS_j if `bad'
		di in gr _n "(data now sorted by $ReS_i $ReS_j)"
		exit
	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?