'Categorizing time data in SAS
I've got the following dataset:
ID time_bed time_wake hours_sleep
1 00:55:00 08:10:00 07:15:00
2 21:15:00 05:00:00 07:45:00
3 02:00:00 07:50:00 05:50:00
I want to categorize the hours of sleep into cat_sleep, where if they slept more than 7:00:00h they'll be a 0 and if they slept lees than 7, it'll be a 1.
data sleep;set final;
time_bed = input(catx(' ',hr_bedhr,hr_bedmin,hr_bedampm),time8.);
time_wake = input(catx(' ',hr_wakehr,hr_wakemin,hr_wakeampm),time8.);
format time_bed time_wake tod8.;
hours_sleep= time_wake - time_bed;
format hours_sleep tod8.;
if hours_sleep >'07:00:00't then cat_sleep=0;
if hours_sleep <= '07:00:00't then cat_sleep=1;
run;
However, I don't get the desire output, which would be as shown below.
ID time_bed time_wake hours_sleep cat_sleep
1 00:55:00 08:10:00 07:15:00 0
2 21:15:00 05:00:00 07:45:00 0
3 02:00:00 07:50:00 05:50:00 1
I've tried with SAStime but I obtain negative values so I have problems trying to categorize it.
Solution 1:[1]
If you already have the hours slept as a time value (number of seconds since midnight) then just compare that to 7 hours.
data want;
set have;
cat_sleep=not (hours_sleep > '07:00't) ;
run;
If you need to calculate the time slept then convert the time values into datetime values so you can just subtract them to get the difference in seconds. If you assume they never slept more than 24 hours then you can just compare the bedtime to the wake time to tell if the wake time is for the next day.
data have;
input ID (time_bed time_wake hours_sleep) (:time.);
format time_bed time_wake hours_sleep time8. ;
cards;
1 00:55:00 08:10:00 07:15:00
2 21:15:00 05:00:00 07:45:00
3 02:00:00 07:50:00 05:50:00
;
data want;
set have;
seconds_asleep = dhms(time_wake<time_bed,0,0,time_wake) - dhms(0,0,0,time_bed);
format seconds_asleep time8.;
cat_sleep=not (seconds_asleep > '07:00't) ;
run;
Result:
time_ hours_ seconds_ cat_
Obs ID time_bed wake sleep asleep sleep
1 1 0:55:00 8:10:00 7:15:00 7:15:00 0
2 2 21:15:00 5:00:00 7:45:00 7:45:00 0
3 3 2:00:00 7:50:00 5:50:00 5:50:00 1
Solution 2:[2]
After the line hours_sleep= time_wake - time_bed; you could add a line:
if hours_sleep < 0 then hours_sleep = hours_sleep + '24:00't;
which should get rid of the negatives where time_bed is before midnight and time_wake is after midnight.
Solution 3:[3]
The first issue is that you cannot compare times the way you tried, i.e using a simple substract operation.
The second issue is that your values are just times, there is no date component. This lack of information complicates the automation of an accurate processing:
On 1st line, it's obvious we have data in the same day
On 2nd line, it's also obvious that time_bed happens the day before time_wake, but this differs from previous line logic.
So, how to proceed?
To compare times, you must use the SAS function intck with an appropriate setup, e.g.:
hours_sleep = intck('minutes', time_bed, time_wake, 'c') / 60;
This statement should returns the time difference expressed in number of hours (check the documentation of intck for more details)
It's a little bit tricky to understand but here you probably need to first estimate the delay in minutes then to divide by 60 to get an accurate value of sleep duration
In order to fix the missing date information, I would add 24 hours when time_bed > time_wake.
Final code:
data want;
set have;
if time_bed > time_wake then time_wake = time_wake + '24:00't;
attrib hours_sleep format=best.;
hours_sleep = abs(intck('minutes', time_bed, time_wake, 'c') / 60);
if hours_sleep > 7 then flag = 1
else flag = 0;
run;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tom |
| Solution 2 | shaun_m |
| Solution 3 |
