computing chronological age

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

computing chronological age

Christine-28
Hi there, I would greatly appreciate some assistance to compute chronological age using SPSS/PASW. I need the output variable to represent (e.g) a chronological age of 12 years, 6 months and 27 days as 12:6:27 (or 12:06:27).

The data is set up as

Int_Date    Child_DOB    Child_Age
25-Aug-08    31-Jul-06    yy:mm:dd
25-Aug-08    15-Dec-04    yy:mm:dd
11-Aug-08    6-Jul-05    yy:mm:dd
6-Aug-08    2-Sep-06    yy:mm:dd
5-Aug-08    22-Feb-06    yy:mm:dd
4-Aug-08    23-Feb-06    yy:mm:dd
8-Sep-08    31-Jul-04    yy:mm:dd


I have looked in help and searched, but I can only find instances where SPSS/PASW formats the date as an untruncated decimal or as individual units.

For reference, I need syntax to represent the results of something like this calculator: http://www.lewisandlewis.com.au/maccalc.html only for the output to be formatted as above.

Thankyou in advance
Christine

Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Clive Downs
Hi Christine,

I think the following syntax (and test data) will produce the output you
want. You can modify it a bit if needed.

It's a bit long winded - no doubt it can be done more succinctly!

Clive

***************

DATA LIST FREE/
    int_date (DATE9) dob(DATE9).
BEGIN DATA
        25-aug-08    31-jul-06
         25-aug-08   15-dec-04
          11-aug-08 06-jul-05
           06-aug-08 02-sep-06
           05-aug-08  22-feb-06
           04-aug-08  23-feb-06
            08-sep-08  31-jul-04
END DATA.


LIST.
* Date and Time Wizard: age.
COMPUTE  age=(int_date - dob) / time.days(1).
VARIABLE LABEL  age.
VARIABLE LEVEL  age (SCALE).
FORMATS  age (F8.2).
VARIABLE WIDTH  age(8).
EXECUTE.



COMPUTE years=age/365.25.
EXECUTE.

COMPUTE wholeYrs=TRUNC(years).
EXECUTE.

COMPUTE Mnths=12*(years-wholeYrs).
EXECUTE.


COMPUTE wholeMnths=TRUNC(Mnths).
EXECUTE.

COMPUTE days=TRUNC(30.42*(Mnths-wholeMnths)).
EXECUTE.
EXE.

STRING ageStr (A9).
COMPUTE ageStr=
  CONCAT(STRING(wholeYrs,N3), ":", STRING(wholeMnths, N2), ":", STRING
(days, N2)).
EXE.

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Richard Ristow
In reply to this post by Christine-28
At 10:13 PM 10/28/2009, Christine wrote:

I would greatly appreciate some assistance to compute chronological age using SPSS/PASW. I need the output variable to represent (e.g) a chronological age of 12 years, 6 months and 27 days as 12:6:27 (or 12:06:27).

I assume you want the standard definition of that, using calendar years and calendar months. If so, the calculation isn't quite straightforward, since neither calendar years nor calendar months have fixed length.

Try this as a solution. The result has to be a character string, because (as stated above), it truly isn't a number.

I'd normally make YD1, MD1, and DD1 scratch variables, but listing them may clarify the logic. I have a feeling I should be using DATEDIFF, but using XDATE functions seems to make the 'borrowing' easier.

And, this is tricky logic. Please, all, inspect it, and post corrections or improvements that you see.

|-----------------------------|---------------------------|
|Output Created               |29-OCT-2009 19:20:19       |
|-----------------------------|---------------------------|
   Int_Date   Child_DOB

25-AUG-2008 31-JUL-2006
25-AUG-2008 15-DEC-2004
11-AUG-2008 06-JUL-2005
06-AUG-2008 02-SEP-2006
05-AUG-2008 22-FEB-2006
04-AUG-2008 23-FEB-2006
08-SEP-2008 31-JUL-2004
08-SEP-2008 09-SEP-2004

Number of cases read:  8    Number of cases listed:  8

 
NUMERIC YD1 MD1 DD1 YD2 MD2 DD2 (F3).

*  Compute the straightforward Y-M-D differences:   ...  .
COMPUTE YD1 = XDATE.YEAR (Int_DAte) - XDATE.YEAR (Child_DOB).
COMPUTE MD1 = XDATE.MONTH(Int_Date) - XDATE.MONTH(Child_DOB).
COMPUTE DD1 = XDATE.MDAY (Int_Date) - XDATE.MDAY (Child_DOB).

*  Correct the Y-M-D differences, eliminating       ...  .
*  negative values by 'borrowing':                  ...  .

*  --- Borrow days, taking the month borrowed as    ---  .
*  --- having 30 days.                              ---  .
*      That seems to be what                             .
*      http://www.lewisandlewis.com.au/maccalc.html       .
*      does, though one could also use the actual        .
*      number of days in the borrowed month.             .

DO IF      DD1 GE  0.
.  COMPUTE DD2 = DD1.
.  COMPUTE MD2 = MD1.
ELSE.
.  COMPUTE DD2 = DD1 + 30.
.  COMPUTE MD2 = MD1 -  1.
END IF.

*  --- Borrow months, from 12-month years.          ---  .
*      Apply the correction to the months-difference     .
*      calculated above, possibly corrected from the     .
*      the straightforward value.                        .

DO IF      MD2 GE  0.
.  COMPUTE YD2 = YD1.
.  COMPUTE MD2 = MD2.
ELSE.
.  COMPUTE YD2 = YD1 -  1.
.  COMPUTE MD2 = MD2 + 12.
END IF.


*  Combine the corrected differences as a single    ...  .
*  character string                                 ...  .

STRING  Child_Age (A8).

COMPUTE Child_Age = CONCAT(STRING(YD2,F2),':',
                           STRING(MD2,N2),':',
                           STRING(DD2,N2)    ).

LIST.
List
|-----------------------------|---------------------------|
|Output Created               |29-OCT-2009 19:20:20       |
|-----------------------------|---------------------------|
   Int_Date   Child_DOB YD1 MD1 DD1 YD2 MD2 DD2 Child_Age

25-AUG-2008 31-JUL-2006   2   1  -6   2   0  24  2:00:24
25-AUG-2008 15-DEC-2004   4  -4  10   3   8  10  3:08:10
11-AUG-2008 06-JUL-2005   3   1   5   3   1   5  3:01:05
06-AUG-2008 02-SEP-2006   2  -1   4   1  11   4  1:11:04
05-AUG-2008 22-FEB-2006   2   6 -17   2   5  13  2:05:13
04-AUG-2008 23-FEB-2006   2   6 -19   2   5  11  2:05:11
08-SEP-2008 31-JUL-2004   4   2 -23   4   1   7  4:01:07
08-SEP-2008 09-SEP-2004   4   0  -1   3  11  29  3:11:29

Number of cases read:  8    Number of cases listed:  8
=============================
APPENDIX: Test data, and code
=============================
DATA LIST LIST/
   Int_Date    Child_DOB
   (DATE11     DATE11).
BEGIN DATA  
   25-Aug-08    31-Jul-06
   25-Aug-08    15-Dec-04
   11-Aug-08    6-Jul-05
   6-Aug-08    2-Sep-06
   5-Aug-08    22-Feb-06
   4-Aug-08    23-Feb-06
   8-Sep-08    31-Jul-04
   8-Sep-08    9-Sep-04
END DATA.
LIST.

NUMERIC YD1 MD1 DD1 YD2 MD2 DD2 (F3).

*  Compute the straightforward Y-M-D differences:   ...  .
COMPUTE YD1 = XDATE.YEAR (Int_DAte) - XDATE.YEAR (Child_DOB).
COMPUTE MD1 = XDATE.MONTH(Int_Date) - XDATE.MONTH(Child_DOB).
COMPUTE DD1 = XDATE.MDAY (Int_Date) - XDATE.MDAY (Child_DOB).

*  Correct the Y-M-D differences, eliminating       ...  .
*  negative values by 'borrowing':                  ...  .

*  --- Borrow days, taking the month borrowed as    ---  .
*  --- having 30 days.                              ---  .
*      That seems to be what                             .
*      http://www.lewisandlewis.com.au/maccalc.html       .
*      does, though one could also use the actual        .
*      number of days in the borrowed month.             .

DO IF      DD1 GE  0.
.  COMPUTE DD2 = DD1.
.  COMPUTE MD2 = MD1.
ELSE.
.  COMPUTE DD2 = DD1 + 30.
.  COMPUTE MD2 = MD1 -  1.
END IF.

*  --- Borrow months, from 12-month years.          ---  .
*      Apply the correction to the months-difference     .
*      calculated above, possibly corrected from the     .
*      the straightforward value.                        .

DO IF      MD2 GE  0.
.  COMPUTE YD2 = YD1.
.  COMPUTE MD2 = MD2.
ELSE.
.  COMPUTE YD2 = YD1 -  1.
.  COMPUTE MD2 = MD2 + 12.
END IF.


*  Combine the corrected differences as a single    ...  .
*  character string                                 ...  .

STRING  Child_Age (A8).

COMPUTE Child_Age = CONCAT(STRING(YD2,F2),':',
                           STRING(MD2,N2),':',
                           STRING(DD2,N2)    ).

LIST.

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Richard Ristow
At 08:02 PM 10/29/2009, Jon K Peck wrote, off-list:

The datediff function calculates exact, calendar-aware intervals in whatever units are requested.

Indeed, DATEDIFF does that, and I thought it should be the tool the tool to use. It makes calculating the years and the months much easier:

COMPUTE YD1  = DATEDIFF(Int_Date,Child_DOB,"Years").
COMPUTE MD1  = DATEDIFF(Int_Date,Child_DOB,"Months").
                       /TIME.DAYS(1).
COMPUTE YD2 = YD1.
COMPUTE MD2 = MOD(MD1,12).

But I can't see how to get the right 'days' value. The code below has a couple of attempts, that don't work at all.

Help, anyone?

=============================
APPENDIX: Test data, and code
=============================
NOT WORKING: the 'days' values are computed wrong, or not at all

DATA LIST LIST/
   Int_Date    Child_DOB
   (DATE11     DATE11).
BEGIN DATA  
   25-Aug-08    31-Jul-06
   25-Aug-08    15-Dec-04
   11-Aug-08    6-Jul-05
   6-Aug-08    2-Sep-06
   5-Aug-08    22-Feb-06
   4-Aug-08    23-Feb-06
   8-Sep-08    31-Jul-04
   8-Sep-08    9-Sep-04
END DATA.
LIST.

NUMERIC YD1  MD1  DD1  DD1A  YD2  MD2  DD2  DD2A (F3).
FORMATS DD1  DD1A DD2  DD2A                      (F5).

COMPUTE YD1  = DATEDIFF(Int_Date,Child_DOB,"Years").
COMPUTE MD1  = DATEDIFF(Int_Date,Child_DOB,"Months").
COMPUTE DD1  = DATEDIFF(Int_Date,Child_DOB,"Days").
COMPUTE DD1A = MOD     (Int_Date - Child_DOB,TIME.DAYS(1))
                       /TIME.DAYS(1).

COMPUTE YD2 = YD1.
COMPUTE MD2 = MOD(MD1,12).
COMPUTE DD2 = MOD(DD1,30).

LIST.

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Clive Downs
In reply to this post by Christine-28
Hello Richard,

Thanks for this - it looks like my suggested solution was a bit too
simplistic!

Regards

Clive

=====================
To manage your subscription to SPSSX-L, send a message to
[hidden email] (not to SPSSX-L), with no body text except the
command. To leave the list, send the command
SIGNOFF SPSSX-L
For a list of commands to manage subscriptions, send the command
INFO REFCARD
Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Jon K Peck
In reply to this post by Richard Ristow

Here's how to get the days correct.  checkcalc below shows that the parts do add up to the later date.

Regards,
Jon

BEGIN DATA  
   25-Aug-08    31-Jul-06
   25-Aug-08    15-Dec-04
   11-Aug-08    6-Jul-05
   6-Aug-08    2-Sep-06
   5-Aug-08    22-Feb-06
   4-Aug-08    23-Feb-06
   8-Sep-08    31-Jul-04
   8-Sep-08    9-Sep-04
END DATA.

COMPUTE YD1  = DATEDIFF(Int_Date,Child_DOB,"Years").
COMPUTE MD1  = DATEDIFF(Int_Date,Child_DOB,"Months").

compute part1 = datesum(child_dob, yd1, "years").
compute monthsremaining = datediff(int_date, part1, "months").

compute part2 = datesum(part1, monthsremaining, "months").
compute days = datediff(int_date, part2, "days").
compute checkcalc = datesum(part2, days, "days").
format part1 part2 checkcalc(adate12).




From: Richard Ristow <[hidden email]>
To: [hidden email]
Date: 10/30/2009 12:02 AM
Subject: Re: [SPSSX-L] computing chronological age
Sent by: "SPSSX(r) Discussion" <[hidden email]>





At 08:02 PM 10/29/2009, Jon K Peck wrote, off-list:

The datediff function calculates exact, calendar-aware intervals in whatever units are requested.

Indeed, DATEDIFF does that, and I thought it should be the tool the tool to use. It makes calculating the years and the months much easier:

COMPUTE YD1  = DATEDIFF(Int_Date,Child_DOB,"Years").
COMPUTE MD1  = DATEDIFF(Int_Date,Child_DOB,"Months").
                      /TIME.DAYS(1).
COMPUTE YD2 = YD1.
COMPUTE MD2 = MOD(MD1,12).

But I can't see how to get the right 'days' value. The code below has a couple of attempts, that don't work at all.

Help, anyone?

=============================
APPENDIX: Test data, and code
=============================
NOT WORKING: the 'days' values are computed wrong, or not at all

DATA LIST LIST/
  Int_Date    Child_DOB
  (DATE11     DATE11).
BEGIN DATA  
  25-Aug-08    31-Jul-06
  25-Aug-08    15-Dec-04
  11-Aug-08    6-Jul-05
  6-Aug-08    2-Sep-06
  5-Aug-08    22-Feb-06
  4-Aug-08    23-Feb-06
  8-Sep-08    31-Jul-04
  8-Sep-08    9-Sep-04
END DATA.
LIST.

NUMERIC YD1  MD1  DD1  DD1A  YD2  MD2  DD2  DD2A (F3).
FORMATS DD1  DD1A DD2  DD2A                      (F5).

COMPUTE YD1  = DATEDIFF(Int_Date,Child_DOB,"Years").
COMPUTE MD1  = DATEDIFF(Int_Date,Child_DOB,"Months").
COMPUTE DD1  = DATEDIFF(Int_Date,Child_DOB,"Days").
COMPUTE DD1A = MOD     (Int_Date - Child_DOB,TIME.DAYS(1))
                      /TIME.DAYS(1).

COMPUTE YD2 = YD1.
COMPUTE MD2 = MOD(MD1,12).
COMPUTE DD2 = MOD(DD1,30).

LIST.


===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD

Reply | Threaded
Open this post in threaded view
|

Re: computing chronological age

Richard Ristow
At 09:31 AM 10/30/2009, Jon K Peck wrote:

Here's how to get the days correct.  checkcalc below shows that the parts do add up to the later date.

Thank you! That is a very nice approach (and much simpler code):
. take the difference in years, then 'advance' the DOB by that amount;
. take the difference in months from that advanced date, and advance again by that amount; and then
. take the difference in days from the twice-advanced date.
Below is the listing from a run with Jon's code.

Here's a comparison of the results, stitched together from the output below and what I posted yesterday. YrDif, MonDif and DayDif are calculated using Jon's logic; YD1 thru DD2 are the differences I calculated.

   Int_Date   Child_DOB YrDif  MonDif     AdvYrMn DayDif YD1 MD1 DD1 YD2 MD2 DD2
                                                        
25-AUG-2008 31-JUL-2006    2       0  31-JUL-2008    25    2   1  -6   2   0  24
25-AUG-2008 15-DEC-2004    3       8  15-AUG-2008    10    4  -4  10   3   8  10
11-AUG-2008 06-JUL-2005    3       1  06-AUG-2008     5    3   1   5   3   1   5
06-AUG-2008 02-SEP-2006    1      11  02-AUG-2008     4    2  -1   4   1  11   4
05-AUG-2008 22-FEB-2006    2       5  22-JUL-2008    14    2   6 -17   2   5  13
04-AUG-2008 23-FEB-2006    2       5  23-JUL-2008    12    2   6 -19   2   5  11
08-SEP-2008 31-JUL-2004    4       1  31-AUG-2008     8    4   2 -23   4   1   7
08-SEP-2008 09-SEP-2004    3      11  09-AUG-2008    30    4   0  -1   3  11  29

Where the interview day-of-month number is less than the DOB day-of-month number, my final 'days' difference (DD2) is 1 less than Jon's (DayDif). That's from my taking months as having 30 days, following the on-line calculator recommended; the months actually 'borrowed' from all have 31 days. Jon's is definitely the recommended value.

Demonstration run, using Jon's logic:
|-----------------------------|---------------------------|
|Output Created               |30-OCT-2009 10:38:10       |
|-----------------------------|---------------------------|
   Int_Date   Child_DOB

25-AUG-2008 31-JUL-2006
25-AUG-2008 15-DEC-2004
11-AUG-2008 06-JUL-2005
06-AUG-2008 02-SEP-2006
05-AUG-2008 22-FEB-2006
04-AUG-2008 23-FEB-2006
08-SEP-2008 31-JUL-2004
08-SEP-2008 09-SEP-2004

Number of cases read:  8    Number of cases listed:  8

 
NUMERIC YrDif     (F3)   AdvYrs    (DATE11)
        MonDif    (F3)   AdvYrMn   (DATE11)
        DayDif    (F3)   checkcalc (DATE11).

COMPUTE YrDif     = DATEDIFF(Int_Date,Child_DOB,"Years").

compute AdvYrs    = datesum (child_dob, YrDif,  "years").
compute MonDif    = datediff(int_date,  AdvYrs, "months").

compute AdvYrMn   = datesum (AdvYrs,    MonDif, "months").
compute DayDif    = datediff(int_date,  AdvYrMn,"days").
compute checkcalc = datesum (AdvYrMn,   DayDif, "days").

LIST.
|-----------------------------|---------------------------|
|Output Created               |30-OCT-2009 10:38:11       |
|-----------------------------|---------------------------|
   Int_Date   Child_DOB YrDif      AdvYrs MonDif     AdvYrMn DayDif   checkcalc

25-AUG-2008 31-JUL-2006    2  31-JUL-2008     0  31-JUL-2008    25  25-AUG-2008
25-AUG-2008 15-DEC-2004    3  15-DEC-2007     8  15-AUG-2008    10  25-AUG-2008
11-AUG-2008 06-JUL-2005    3  06-JUL-2008     1  06-AUG-2008     5  11-AUG-2008
06-AUG-2008 02-SEP-2006    1  02-SEP-2007    11  02-AUG-2008     4  06-AUG-2008
05-AUG-2008 22-FEB-2006    2  22-FEB-2008     5  22-JUL-2008    14  05-AUG-2008
04-AUG-2008 23-FEB-2006    2  23-FEB-2008     5  23-JUL-2008    12  04-AUG-2008
08-SEP-2008 31-JUL-2004    4  31-JUL-2008     1  31-AUG-2008     8  08-SEP-2008
08-SEP-2008 09-SEP-2004    3  09-SEP-2007    11  09-AUG-2008    30  08-SEP-2008

Number of cases read:  8    Number of cases listed:  8
=============================
APPENDIX: Test data, and code
=============================
DATA LIST LIST/
   Int_Date    Child_DOB
   (DATE11     DATE11).
BEGIN DATA  
   25-Aug-08    31-Jul-06
   25-Aug-08    15-Dec-04
   11-Aug-08    6-Jul-05
   6-Aug-08    2-Sep-06
   5-Aug-08    22-Feb-06
   4-Aug-08    23-Feb-06
   8-Sep-08    31-Jul-04
   8-Sep-08    9-Sep-04
END DATA.
LIST.


NUMERIC YrDif     (F3)   AdvYrs    (DATE11)
        MonDif    (F3)   AdvYrMn   (DATE11)
        DayDif    (F3)   checkcalc (DATE11).

COMPUTE YrDif     = DATEDIFF(Int_Date,Child_DOB,"Years").

compute AdvYrs    = datesum (child_dob, YrDif,  "years").
compute MonDif    = datediff(int_date,  AdvYrs, "months").

compute AdvYrMn   = datesum (AdvYrs,    MonDif, "months").
compute DayDif    = datediff(int_date,  AdvYrMn,"days").
compute checkcalc = datesum (AdvYrMn,   DayDif, "days").

LIST.

===================== To manage your subscription to SPSSX-L, send a message to [hidden email] (not to SPSSX-L), with no body text except the command. To leave the list, send the command SIGNOFF SPSSX-L For a list of commands to manage subscriptions, send the command INFO REFCARD