Date: Tue, 1 Mar 2005 19:52:07 -0500
Reply-To: Richard Ristow <wrristow@mindspring.com>
Sender: "SPSSX(r) Discussion" <SPSSX-L@LISTSERV.UGA.EDU>
From: Richard Ristow <wrristow@mindspring.com>
Subject: Re: eliminate readmissions on discharge date
In-Reply-To: <5801DF3664AC854AA3CC2DB83E718D306795B1@sagemsg0006.sagemsm
rd01.sa.gov.au>
Content-Type: text/plain; charset="us-ascii"; format=flowed
At 06:29 PM 3/1/2005, Barnett, Adrian (HEALTH) wrote:
>Thanks for your careful analysis of the code. It was a rude shock to
>discover the way that original final ELSE IF clause was failing. I
>still don't understand why. :-(
As to that: here's your full original syntax (minus SORT CASES):
Do if (personid eq lag(personid)).
* grabs subsequent admissions which weren't on the same day they
were discharged from previous admission.
- if (admdate ne lag(disdate)) f = 1.
* ensure you grab the first record for a person and also
the first record in the file:.
Else if ((personid ne lag(personid)) or $casenum eq 1).
- compute f = 1.
End if.
The final ELSE IF clause is not failing. For the very first case in the
file (which is the problem), it's the DO IF clause at the beginning
that's failing. Since
. lag(personid)
is missing for the first case, the conditional expression
. (personid eq lag(personid))
also evaluates as missing. But, per a famous SPSS decision (with much
in its favor, but also a major 'gotcha'),
>>"Missing values returned by the logical expression on DO IF or on any
>>ELSE IF cause control to pass to the END IF command at that point." -
>>SPSS syntax manual.
>However, I did find a way of reworking the code which overcomes the
>error. It's a bit brute-force, but it's clear and (this time) it works.
Exactly so. First, you have
Do if ($casenum eq 1).
- compute f = 1.
That tests 'true' for the first case in the file (as, of course, you
intend). Once a clause has tested 'true', later ELSE IF and ELSE
clauses are skipped. The clause
Else if (personid ne lag(personid)) .
would still test 'missing' for the first case in the file; but, for
that case, it's never reached.
>[It works] in one pass. Although I've got a LIST in there, it's just
>for demo purposes - a FILTER statement run without it still selects
>the desired cases.
Yes; and so does a SELECT IF, which is much more dangerous. See
successful run, below, with 'instrumentation' to list current and
lagged values during processing of each case. I have an EXECUTE
statement before the LIST, but it's only to separate the output from
the PRINT commands from the output of LIST.
. When a case is rejected, the case number ($CASEID) does not change
when a new case is read. (See case=5, two instances.)
. The lagged values are the values of the last previous case that is
KEPT. I suppose that would cause a case to be kept erroneously, if its
admission date was the same as the previous discharge date, AND the
previous case was itself rejected because its admission date matched
the discharge date before that.
Logic using LAG and SELECT IF in the same pass is still dangerous,
generally to be avoided. (FILTER instead of SELECT IF is safe.) It's
recommended to either do two passes (an EXECUTE before the SELECT IF
will do this), or use some logic other than LAG, or at least check the
logic you have, very carefully.
* --- Illustration, with SELECT IF and PRINT statements.
* grab the first record for [the file] .
Do if ($casenum eq 1).
- compute f = 1.
* Always select the first instance of a person.
Else if (personid ne lag(personid)) .
- compute f = 1.
* grabs subsequent admissions which weren't on the same day .
* they were discharged from previous admission .
else if (personid eq lag(personid)).
- if (admdate ne lag(disdate)) f = 1.
End if.
* --- Code from here on is "instrumentation" --- .
PRINT / 'Case' $CASENUM (F2)
'Prsn ' 10 PERSONID ' Admit ' ADMDATE ' Disch ' DISDATE.
NUMERIC #LAG_PRS (F3)
/#LAG_ADM #LAG_DIS (DATE11).
COMPUTE #LAG_PRS = LAG(PERSONID).
COMPUTE #LAG_ADM = LAG(ADMDATE).
COMPUTE #LAG_DIS = LAG(DISDATE).
PRINT / ' Lag'
'Prsn ' 10 #LAG_PRS ' Admit ' #LAG_ADM ' Disch ' #LAG_DIS.
PRINT / 'f= ' 10 f.
SELECT IF (F=1).
EXECUTE.
Case 1 Prsn 101 Admit 10-JAN-2005 Disch 12-JAN-2005
Lag Prsn . Admit . Disch .
f= 1.00
Case 2 Prsn 102 Admit 10-JAN-2005 Disch 12-JAN-2005
Lag Prsn 101 Admit 10-JAN-2005 Disch 12-JAN-2005
f= 1.00
Case 3 Prsn 102 Admit 01-FEB-2005 Disch 03-FEB-2005
Lag Prsn 102 Admit 10-JAN-2005 Disch 12-JAN-2005
f= 1.00
Case 4 Prsn 103 Admit 10-JAN-2005 Disch 12-JAN-2005
Lag Prsn 102 Admit 01-FEB-2005 Disch 03-FEB-2005
f= 1.00
Case 5 Prsn 103 Admit 12-JAN-2005 Disch 14-JAN-2005
Lag Prsn 103 Admit 10-JAN-2005 Disch 12-JAN-2005
f= .
Case 5 Prsn 104 Admit 10-JAN-2005 Disch 15-JAN-2005
Lag Prsn 103 Admit 10-JAN-2005 Disch 12-JAN-2005
f= 1.00
Case 6 Prsn 104 Admit 15-JAN-2005 Disch 20-JAN-2005
Lag Prsn 104 Admit 10-JAN-2005 Disch 15-JAN-2005
f= .
Case 6 Prsn 104 Admit 01-FEB-2005 Disch 04-FEB-2005
Lag Prsn 104 Admit 10-JAN-2005 Disch 15-JAN-2005
f= 1.00
Case 7 Prsn 104 Admit 04-FEB-2005 Disch 08-FEB-2005
Lag Prsn 104 Admit 01-FEB-2005 Disch 04-FEB-2005
f= .
Case 7 Prsn 105 Admit 01-FEB-2005 Disch 07-FEB-2005
Lag Prsn 104 Admit 01-FEB-2005 Disch 04-FEB-2005
f= 1.00
LIST.
List
PERSONID ADMIT ADMDATE DISDATE DESIRED F
101 A 10-JAN-2005 12-JAN-2005 Yes 1.00
102 A 10-JAN-2005 12-JAN-2005 Yes 1.00
102 B 01-FEB-2005 03-FEB-2005 Yes 1.00
103 A 10-JAN-2005 12-JAN-2005 Yes 1.00
104 A 10-JAN-2005 15-JAN-2005 Yes 1.00
104 C 01-FEB-2005 04-FEB-2005 Yes 1.00
105 A 01-FEB-2005 07-FEB-2005 Yes 1.00
Number of cases read: 7 Number of cases listed: 7