Stata The Stata listserver
[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

Re: st: RE: RE: loop [ignore previous one (from this message), sorry!!!]


From   "Jun Xu" <mystata@hotmail.com>
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: RE: RE: loop [ignore previous one (from this message), sorry!!!]
Date   Mon, 17 Feb 2003 18:45:11 -0600

Nick,

Thank you so much. After I made that change "gen long `pat02'=." it worked. Also thank you for your hints/program. Probably I shouldn't ve posted this question. Rather I better to take a course in programming. But if you have the answer at hand, would you be able to give me some general rules/if possible, some tricks for this problem to be more efficient? This program now works pretty fine with less than like 12 variables. Everything works fine except a bit slow (10 and less variables kind of fast enough). But when I play around with it using like 15 variables, it just takes forever to produce the results (like 10 minutes). I think it's probably related to the forval command in the middle part of this program. But I couldn't find a better way. Or, if I want program an ado file to do what I want (exhaust combinations), slowness should be expected. Thanks again. By the way, you're amazing!!! Some parts of the following program is wrapped-up and actually should be in one line due to the hotmail set up that I have. Not sure how it is displayed in the statalist

Jun Xu
Department of Sociology
Indiana University at Bloomington

***********************************************************************
*! version beta 0.0.1 02/15/2003

capture program drop permlist
program define permlist, rclass
version 7

preserve

tempvar pat02 pat10 varpat patfrq count miscnt hasmis

syntax varlist [,PATCORrelate(numlist) PATMIS(numlist) PATRESP SAVE(string)]
tokenize `varlist'
local nvars : word count `varlist'

while "`1'"!="" {
forval i=1/`nvars'{
local curvar`i': word `i' of `varlist'
*di "`curvar`i''"
}
macro shift
}


local imax=2^`nvars'-1


*di `imax'
*di `nvars'

/*
if _n<`imax' {
local org_n=_n
set obs `imax'
}
*/

quietly gen long `pat02'=.
quietly gen `pat10'=.
quietly gen `patfrq'=.
quietly gen str50 `varpat'=""
quietly gen `miscnt'=.

forval i = 1 / `imax' {
local addon ""

qui inbase 2 `i'

*=>di %0`nvars'.0f `r(base)' here is to display
* `r(base)' with its full length. For example
* for 1 if we want to have five digit number (should
* be equal to number of variables in this case
* 1 will be displayed as 00001

local which : di %0`nvars'.0f `r(base)'
*di "`which'"

forval j = 1 / `nvars' {

*=>substr(s,n1,n2) returns the substring of s
* starting at n1 for a length of n2

local char = substr("`which'",`j',1)

if "`char'"=="0"{
local addon "`addon'"

if "`j'"=="1"{
local ifqlf "`curvar`j''==0"
}

if "`j'">"1"{
local ifqlf "`ifqlf' & `curvar`j''==0"
}

}

if "`char'"=="1" {
local addon "`addon' `curvar`j''"
if "`j'"=="1"{
local ifqlf "`curvar`j''==1"
}

if "`j'">"1"{
local ifqlf "`ifqlf' & `curvar`j''==1"
}


}


}

quietly replace `pat02' =`which' if _n==`i'
quietly replace `pat10' =`i' if _n==`i'
quietly replace `varpat' ="`addon'" if _n==`i'
format `pat02' %0`nvars'.0f `r(base)'



quietly {
gen `count'=(`ifqlf')
sum `count', d
replace `patfrq'=`r(sum)' if _n==`i'
}
drop `count'

mark `hasmis'
markout `hasmis' `addon'
quietly sum `hasmis', d
local cntmis=`r(sum)'
quietly replace `miscnt'=`cntmis' if _n==`i'
quietly drop `hasmis'


}

*di "`addon'"
label var `pat02' pat02
label var `patfrq' patfrq
label var `miscnt' nomiscnt

if "`patresp'"~=""{
di _n(1) in g "Response Pattern of Binary(0/1) Indicators:"
tabdisp `pat02' if `pat02'~=., cell(`patfrq')
di _n(1) _skip(2) in g " pat02 = binary codes of in/out in varlist "
di _skip(2) in g " patfrq = obs counts of a response pattern."

}

di _n(2)
if "`patcorrelate'"=="0" {
forval n=1 / `imax'{
local a=`varpat'[`n']
corr `a'
}
}

if "`patcorrelate'"~="" & "`patcorrelate'"~="0" {

qui inten 2 `patcorrelate'
local a=r(ten)
local b=`varpat'[`a']
corr `b'

}

if "`patmis'"~=""{
di _n(1) in g "Counts of Nonmissing Cases in a Varlist:"
tabdisp `pat02' if `pat02'~=., cell(`miscnt')
di _n(1) _skip(2) in g " pat02 = binary codes of in/out in varlist "
di _skip(2) in g "nomiscnt = counts of nonmissing cases."

qui inten 2 `patmis'
local c=r(ten)
local d=`varpat'[`c']
local e=`miscnt'[`c']
di _n(3) in y "The nonmissing sample size for only `d' is `e'"

quietly sort `miscnt'

di _n(2)
di in g "pat02 / varpat / miscnt: top 10 or less nonmissing varlist"
di _n(1)


if `imax'<=10 {
list `pat02' `varpat' `miscnt' in 1/`imax', noobs noheader
}

else {
list `pat02' `varpat' `miscnt' in 1/10, noobs noheader
}


local lowb=`imax'-10

di _n(2)
di in g "pat02 / varpat / miscnt: bottom 10 or less nonmissing varlist"
di _n(1)


if `lowb'<=0 {
list `pat02' `varpat' `miscnt' in 1/`imax', noobs noheader
}

else {
list `pat02' `varpat' `miscnt' in `lowb'/`imax', noobs noheader
}


}


if "`save'"~=""{
preserve
drop if _n>`imax'
rename `pat02' _patbin_
rename `varpat' _varpat_
rename `miscnt' _miscnt_
rename `patfrq' _patfrq_
keep _patbin_ _varpat_ _miscnt_ _patfrq_
quietly gen str50 _varlist_="`varlist'"
save "`save'", replace
restore
}


return local varlist `"`varlist'"'


end

exit

clear
set more off
for num 1/6: set obs 100\ gen xX=invnorm(uniform()) \ gen DxX=xX>0.6
aorder
egen all = concat(Dx1-Dx6)
tab all

rename Dx1 m1
rename Dx2 y3
rename Dx5 z4

recode Dx3 1=. if _n>80
recode z4 0=. if _n>60 & _n<80
permlist Dx3 y3 Dx4 z4 Dx6 m1, patmis(001111) save(H:\my)
********************************************************************






From: "Nick Cox" <n.j.cox@durham.ac.uk>
Reply-To: statalist@hsphsun2.harvard.edu
To: <statalist@hsphsun2.harvard.edu>
Subject: st: RE: RE: loop [ignore previous one (from this message), sorry!!!]
Date: Sun, 16 Feb 2003 17:42:27 -0000

Jun Xu wrote

> This email might be kind of long, but to explain this
> problem clearly, could
> you bear with me for a second :( Thanks a lot.
>
> Thanks a lot for your help, and I have managed to write an
> ado file that
> seems to work fine till I found out that it won't work with
> a varlist of
> more than 8. I have attached our previous Q&A emails at the end.
>
> Notes:
>
> `imax': here is a macro that I have grabbed using 2^`nvars'-1.
> `nvars': is a macro containing number of variables in the varlist.
>
> part of the ado file that's relevant to my question
> ************************************************************
> ************
> ......
> ......
> ......
> *create this response pattern variabl and replace the value
> in future
> quietly gen `pat02'=.
> format `pat02' %0`nvars'.0f
>
> *create other tempvars
>
> forval i = 1 / `imax' {
> qui inbase 2 `i'
>
>
> local which : di %0`nvars'.0f `r(base)'
>
> *local a="`which'"
> *di "`which'"
>
> forval j = 1 / `nvars' {
> local char = substr("`which'",`j',1)
>
> *I only invoke `which' once within this loop
> .......
> .......
> .......
>
> }
>
>
> quietly replace `pat02'=`which' if _n==`i'
>
> *I don't see what's wrong here and I have used the
> following three *lines
> kind of check the instantaneous value of `which' and it is
> a *binary code
> everytime, but `pat02'[`i'] becomes not binary after the
> *binary code
> 100000000, so I strongly suspect either I misused the
> *replace statement, or
> there is something unique to "local which : di
> %*0`nvars'.0f `r(base)'" the
> command that Nick taught me in his email to *my question,
> which I might not
> understand well. The puzzle here is *that no problems with
> 8 variables and
> less, but not 9 variables and *above as you will see in the
> output, where
> the binary codes will have *other values than 0 and 1.

In your code `pat02' is created as a -float-. That
is, you didn't specify a variable type, so Stata created `pat02'
as a -float- (unless, as seems unlikely, you earlier -set type
double-).
There aren't enough bits in a float value to ensure that your
larger "binary" numbers are held absolutely exactly, which you
need for this problem.

The heart of the difficulty is shown by this example:

. set obs 1
. gen myvar = 11111111
. d myvar

storage display value
variable name type format label variable label
----------------------------------------------------------------------
---------
myvar float %9.0g

. format myvar %9.0f

. l

+----------+
| myvar |
|----------|
1. | 11111111 |
+----------+

. replace myvar = 111111111
(1 real change made)

. l

+-----------+
| myvar |
|-----------|
1. | 111111112 |
+-----------+

That is, despite your -format- some inaccuracy is creeping
once you have figures about as big as 10^9. (Of course,
Stata does not know that you are privately thinking of these
decimals as binary numbers.)

I think you would be better off using a -long- or
a -string- representation.

Here is some code which I think is close to what
you want.

*! NJC 16 February 2003
program countnonmissing
version 7
syntax varlist
tokenize `varlist'
local nvars : word count `varlist'
local imax = 2^`nvars' - 1

qui {
forval i = `imax'(-1)1 {
inbase 2 `i'
local which : di %0`nvars'.0f `r(base)'
noi di "{txt}`which' " _c
local vars
forval j = 1 / `nvars' {
local char = substr("`which'",`j',1)
if `char' {
local vars "`vars'``j'' "
}
}
local nv : word count `vars'
local nvm1 = `nv' - 1
local W
forval j = 1 / `nvm1' {
local wj : word `j' of `vars'
local W "`W'`wj',"
}
local wj : word `nv' of `vars'
local W "`W'`wj'"
count if !missing(`W')
noi di %6.0f r(N)
}
}
end

e.g.
countnonmissing *
countnonmissing make mpg rep78

Nick
n.j.cox@durham.ac.uk

*
* For searches and help try:
* http://www.stata.com/support/faqs/res/findit.html
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/

_________________________________________________________________
Protect your PC - get McAfee.com VirusScan Online http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963

*
* For searches and help try:
* http://www.stata.com/support/faqs/res/findit.html
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/




© Copyright 1996–2014 StataCorp LP   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index