/*_________________________________________________________________________________________ Series: SAS Code for Accelerometer Data Cleaning and Management Name: Step 3 - Derive Variables Date: July 30, 2015 For: Healthy Start / Départ Santé Purpose: Apply published intensity cut-points to data and determine time spent in sedentary, light, moderate and vigorous physical activity. Sum of steps per day is also calculated. Input: Perminute (from Step 2) (Epoch count and step data with non-wear dummy variables) Weartime (from Step 2) (Wear time data) Output: Perday (Daily count and step data) Info: This series of codes is based on the scripts prepared by Statistics Canada for the analysis of data from the Health Measures Survey, the Actical Accelerometer Data Analysis Support Tool (Accel+), which is available from the CHEO Research Institute for Healthy Active Living and Obesity Research (HALO) (http://www.haloresearch.ca/accel/). The current version of this code was prepared by Jonathan Boudreau and Mathieu Bélanger at the Centre de Formation Médicale du Nouveau-Brunswick (CFMNB). Version: 1.3 Citation: Boudreau, J. & Bélanger, M. SAS Code for Accelerometer Data Cleaning and Management: Step 3 - Derive Variables, Version 1.3. http://mathieubelanger.recherche.usherbrooke.ca/Actical.htm#2-5. Updated July 30, 2015. Accessed [date accessed: month day, year]. _________________________________________________________________________________________*/ /****************** STEP 3.1 SPECIFY A WORK DIRECTORY ***********************************************/ * Make sure you are using the same one as in Code Step 1 and Code Step 2. *----------------------------------------------------------------------------------------------------*; %LET po_path1 = C:\Users\Example\SAS Output; /****************** STEP 3.2 SPECIFY A LOCATION FOR THE EXCEL FILE OUTPUT ****************************/ * Specify an Excel file to output your summary dataset. *----------------------------------------------------------------------------------------------------*; %LET xls_path = &po_path1.\PATimes.xls; /****************** STEP 3.3 SPECIFY INTENSITY LEVEL THRESHOLDS **************************************/ * By default, the thresholds for kids are: light = 100 moderate = 1500 vigorous = 6500; *----------------------------------------------------------------------------------------------------*; %LET light = 100; %LET moderate = 1500; %LET vigorous = 6500; /****************** STEP 3.4 SET LABELS *********************************************************/ /* Define the labels to be applied to the subsets. */ *----------------------------------------------------------------------------------------------------*; %LET dc_text = Daycare Hours Only; /* Labels applied to values in the subset specified in Step 2.5 */ %LET ndc_text = Non-daycare Hours Only; /* Labels applied to values outside the subset specified in Step 2.5 */ /****************** STEP 3.5 EPOCH LENGTH AND UNIT CONVERSION ****************************************/ /* Define the desired epoch length in seconds. Valid options are 1, 15, 30 and 60 seconds. The constant for unit conversion from epoch lengths into minutes is computed automatically. The epoch lengths must be the same as in Code Step 1 and Code Step 2. The default value is set for 15 second epochs. */ *----------------------------------------------------------------------------------------------------*; %LET epoch_length = 15; %LET conv_epoch = %EVAL(60/&epoch_length.); /* Do not change. */ /****************** STEP 3.6 SET BOUT LENGTH *********************************************************/ /* Set the bout length criterion (in epoch lengths). */ *----------------------------------------------------------------------------------------------------*; %LET bout_lgth = 1; /* Number of epoch lengths in a bout. Set to 1 epoch length by default. */ /****************** STEP 3.7 SET BOUT INTERVAL DURATION **********************************************/ /* Set the duration of time interval of interest (in minutes). */ *-----------------------------------------------------------------------------------------------------*; %LET bout_time = 10; /* Duration of the time interval of interest in minutes. Set to 10 minutes by default. */ %LET bout_min = 8; /* Minimum number of miniutes at which the cutoff point is attained during the time interval of interest. Set to 8 minutes by default */ /****************** STEP 3.8 EXECUTION ****************************************************************/ /* From this point onwards, no modifications are required for Code Step 3. */ *----------------------------------------------------------------------------------------------------*; /* Outputs */ LIBNAME outlib "&po_path1"; *-----------------------------------------------------------------------------------------------*; * Read in perminute file from Code Step 2. *; * Check general stats (N, mean, SD, min, max) of counts and steps per day. *; *-----------------------------------------------------------------------------------------------*; DATA perminute; SET outlib.perminute; RUN; PROC SORT DATA = perminute; BY clinicid dayworn; RUN; /* All hours */ PROC MEANS DATA = perminute NOPRINT; VAR amcount; OUTPUT OUT = check_amcount; BY clinicid dayworn; RUN; PROC MEANS DATA = perminute NOPRINT; VAR amstep; OUTPUT OUT = check_amstep; BY clinicid dayworn; RUN; /* Subset hours only */ PROC MEANS DATA = perminute(WHERE=(DCHOURS=1)) NOPRINT; VAR amcount; OUTPUT OUT = check_amcount_dc; BY clinicid dayworn; RUN; PROC MEANS DATA = perminute(WHERE=(DCHOURS=1)) NOPRINT; VAR amstep; OUTPUT OUT = check_amstep_dc; BY clinicid dayworn; RUN; /* Non-subset hours only */ PROC MEANS DATA = perminute(WHERE=(DCHOURS=0)) NOPRINT; VAR amcount; OUTPUT OUT = check_amcount_ndc; BY clinicid dayworn; RUN; PROC MEANS DATA = perminute(WHERE=(DCHOURS=0)) NOPRINT; VAR amstep; OUTPUT OUT = check_amstep_ndc; BY clinicid dayworn; RUN; /* Sum of steps per valid day */ PROC MEANS DATA = perminute NOPRINT; VAR amstep; OUTPUT OUT=sumstep SUM=amstep; BY clinicid dayworn; RUN; /* Sum of steps per valid day for subset hours only */ PROC MEANS data = perminute(WHERE=(DCHOURS=1)) NOPRINT; VAR amstep; OUTPUT OUT=sumstep_dc SUM=amstep_dc; BY clinicid dayworn; RUN; /* Sum of steps per valid day for non-subset hours only */ PROC MEANS DATA = perminute(WHERE=(DCHOURS=0)) NOPRINT; VAR amstep; OUTPUT OUT=sumstep_ndc SUM=amstep_ndc; BY clinicid dayworn; RUN; /* Day of the week worn */ DATA dayofweek(KEEP=am_identify_no clinicid dayworn dayofweek_worn a); SET perminute; BY clinicid dayworn; IF first.dayworn; a = left(dayofweek_worn); run; DATA dayofweek(RENAME=(a=dayofweek_worn)); SET dayofweek; DROP dayofweek_worn; RUN; *-----------------------------------------------------------------------------------------------*; * Determine the number of minutes of sedentary, light, moderate, vigorous, moderate or vigorous,*; * or all physical activity for waking hours. *; * *; * NOTE: The follow produces two types of outputs: *; * - One based on bouts defined by the number epoch lengths specified in Code Step 3.6,*; * - One based on the time interval specified in Code Step 3.7. *; * *; *-----------------------------------------------------------------------------------------------*; * *; * Activity bouts defined by specified number of minutes with intensity count >= the threshold. *; * *; * An activity bout starts at an epoch length with an intensity count greater than or equal to *; * the threshold. Epoch length with intensity count greater than or equal to the threshold are *; * considered to be valid for the activity bout. A bout is established when the specified length *; * of consecutive valid epoch lengths are reached. The activity bout stops when any of the *; * following conditions are met: *; * - one epoch length with intensity < threshold *; * - one epoch lenght with a missing intensity count *; * - the last minute of the day. *; *-----------------------------------------------------------------------------------------------*; *-----------------------------------------------------------------------*; * Flag the intensity counts that are above the threshold. *; * Different activity bout criteria are used for different age groups. *; * NOTE: To change the cutoff points for moderate or vigorous intensity, *; * please modify the statements below for variables *; * sedthres(sedentary threshold), ltthresh(light threshold), *; * modthresh(moderate threshold) and vigthresh(vigorous threshold).*; *-----------------------------------------------------------------------*; *Reference: Metabolic Equivalents (METs) low = 1-3 light < 3 moderate = 3.00-5.99 hard = 6.00-8.99 very hard = 9.00+ vigorous = 6.00+ MVPA = 3.00+ ; *Intensity Thresholds - "Published Thresholds" "sedentary" where counts > 0 and counts < 100 "light" where counts >= 100 and counts < moderate threshold "moderate" where counts >= moderate threshold and counts < vigorous threshold "vigorous" where counts >= vigorous threshold "MVPA" where counts >= moderate threshold "light, moderate, or vigorous" where counts >= light threshold ; DATA bouts; SET perminute; /* Light threshold */ ltthresh=0; IF nonwear=0 AND dayworn<=7 THEN ltthresh=(&light./&conv_epoch.); /* this is the sedentary/light cut-point for children (Wong et al., 2011)*/ /* Moderate threshold */ modthresh=0; IF nonwear=0 AND dayworn<=7 THEN modthresh=(&moderate./&conv_epoch.); /* this is the moderate cut-point for children (Puyau et al., 2004)*/ /* Vigorous threshold */ vigthresh=0; IF nonwear=0 AND dayworn<=7 THEN vigthresh=(&vigorous./&conv_epoch.); /* this is the vigorous cut-point for children (Puyau et al., 2004)*/ /* Light, moderate, or vigorous activity */ IF nonwear=0 AND amcount>=ltthresh THEN _pa=1; ELSE IF amcount ne . THEN _pa=0; /* Moderate or vigorous activity */ IF nonwear=0 AND amcount>=modthresh THEN _mv=1; ELSE IF amcount ne . THEN _mv=0; /* Vigorous activity */ IF nonwear=0 AND amcount>=vigthresh THEN _v=1; ELSE IF amcount ne . THEN _v=0; /* Moderate activity */ IF nonwear=0 AND modthresh<=amcount= the threshold is encountered. */ IF &bout_flg=1 AND start=0 THEN DO; strt_mv=obsn; /* Assign the starting epoch of the bout. */ start=1; IF mv_cnt=0 THEN last_mv=obsn; END; /* Stop or reset if obsn is not adjacent to the last obsn */ IF NOT mv_cnt EQ 0 THEN DO; IF obsn EQ last_mv + 1 THEN last_mv = obsn; ELSE IF mv_cnt<&boutperiod THEN reset = 1; ELSE stopped = 1; IF reset OR stopped THEN DO; eoi = 1; GOTO outputobs; END; END; /* Accumulate epochs with intensity counts >= the threshold. */ IF start=1 AND &bout_flg=1 THEN DO; mv_cnt=mv_cnt+1; end_mv=obsn; /* Keep track of the ending epoch for the bout. */ END; /* Stop when an epoch with intensity < threshold or a missing value is encountered. */ IF &bout_flg IN (0,.) THEN DO; IF mv_cnt<&boutperiod THEN reset=1; /* Reset if less than the bout length. */ ELSE stopped=1; END; /* Last minute of the day. */ IF last.dayworn AND mv_cnt>=&boutperiod THEN stopped=1; /* Output one record for each activity bout. */ outputobs: IF stopped=1 THEN DO; dur_mv=end_mv-strt_mv+1; mv_num=mv_num+1; OUTPUT; LABEL strt_mv='Starting epoch for the activity bout' end_mv='Ending epoch for the activity bout' dur_mv='Duration(epoch lengths) of the activity bout' mv_num='Number of the activity bout' ; END; IF eoi=1 THEN GOTO resetobs; KEEP am_identify_no clinicid dayworn mv_num strt_mv end_mv dur_mv ; RUN; PROC SORT DATA=out&bout_flg&boutperiod; BY clinicid dayworn mv_num; RUN; *------------------------------------------------*; * Calculate total duration of activity bouts for *; * each day (in epoch lengths). *; *------------------------------------------------*; PROC SUMMARY DATA=out&bout_flg&boutperiod; BY clinicid dayworn; VAR dur_mv; OUTPUT OUT=sum_mv SUM=tot_dur_mv_brut; RUN; *------------------------------------------------*; * Output one record per day for each person in *; * the analysis (in minutes). *; *------------------------------------------------*; DATA out&bout_flg&boutperiod._sum; MERGE sum_all(in=in_all) sum_mv; BY clinicid dayworn; IF in_all; IF tot_dur_mv_brut=. THEN tot_dur_mv=.; ELSE tot_dur_mv = tot_dur_mv_brut / &convfct; IF tot_dur_mv=. THEN tot_dur_mv=0; %IF &dchr=. %THEN %LET text = ; %ELSE %IF &dchr=1 %THEN %LET text = (&dc_text.); %ELSE %IF &dchr=0 %THEN %LET text = (&ndc_text.); LABEL %IF &bout_flg=_pa %THEN %DO; tot_dur_mv="Total duration (minutes) of light, moderate, or vigorous activity bouts in a day &text" %END; %IF &bout_flg=_mv %THEN %DO; tot_dur_mv="Total duration (minutes) of moderate or vigorous activity bouts in a day &text" %END; %IF &bout_flg=_m %THEN %DO; tot_dur_mv="Total duration (minutes) of moderate activity bouts in a day &text" %END; %IF &bout_flg=_v %THEN %DO; tot_dur_mv="Total duration (minutes) of vigorous activity bouts in a day &text" %END; %IF &bout_flg=_sed %THEN %DO; tot_dur_mv="Total duration (minutes) of sedentary activity bouts in a day &text" %END; %IF &bout_flg=_lt %THEN %DO; tot_dur_mv="Total duration (minutes) of light activity bouts in a day &text" %END; ; KEEP clinicid dayworn tot_dur_mv; RENAME tot_dur_mv=tot_dur&bout_flg&boutperiod; RUN; %MEND bouts; *-----------------------------------------------*; * Create activity bouts for sedentary, light, *; * moderate, vigorous, moderate or vigorous, and *; * all physical activity intensities. *; *-----------------------------------------------*; %MACRO bouts_grp(boutperiod,dchr); %bouts(bout_flg=_mv,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %bouts(bout_flg=_v,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %bouts(bout_flg=_m,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %bouts(bout_flg=_sed,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %bouts(bout_flg=_lt,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %bouts(bout_flg=_pa,boutperiod=&boutperiod,convfct=&conv_epoch.,dchr=&dchr); %MEND bouts_grp; *---------------------------------------------------------------------------------------------*; * Macro %bouts_8of10 defines activity bouts of the duration specified in Code Step 3.7 with *; * intensity counts >= the threshold. *; * *; * An activity bout starts with a count that is greater than or equal to the threshold. *; * A bout is established when the minimum number of minutes with intensity counts greater than *; * or equal to the threshold is attained. The bout stops when any of the following conditions *; * are met: *; * - the maximum allowable number of minutes with intensity < threshold is attained *; * - one epoch with a missing intensity count *; * - last epoch of the day *; * *; * Macro call %bouts_8of10(bout_flg=); *; * bout_flg: variable name for activity bout intensity: *; * _sed(sedentary), *; * _lt(light), *; * _m(moderate), *; * _v(vigorous), *; * _mv(moderate or vigorous) *; *---------------------------------------------------------------------------------------------*; %MACRO bouts_8of10(bout_flg=,convfct=,min_win=,max_win=,dchr=); DATA out&bout_flg; %IF &dchr = . %THEN %DO; SET bouts; %END; %ELSE %DO; SET bouts(WHERE=(DCHOURS=&dchr)); %END; BY clinicid dayworn obsn; /* Set up the window of predefined length. */ ARRAY win_obsn(*) win_obsn1-win_obsn&max_win; /* Epoch */ ARRAY win_int(*) win_int1-win_int&max_win; /* Intensity */ ARRAY win_flg(*) win_flg1-win_flg&max_win; /* Bout flag */ IF first.dayworn THEN DO; mv_num=0; /* Number of activity bouts. */ last_mv=0; /* Previous observation number */ END; resetobs: IF first.dayworn OR stopped OR reset THEN DO; strt_mv=0; /* Starting minute for the bout. */ end_mv=0; /* Ending minute for the bout. */ found=0; /* Set to 1 if a bout has been established. */ reset=0; /* Reset the counts and start over. */ stopped=0; /* Indicator for stopping the bout. */ start=0; /* Start set to 1 if one epoch above the threshold count is encountered. */ mv_cnt=0; /* Number of epochs with counts >= the threshold. */ sum10=.; /* The total intensity counts from the window. */ cnt_below=0; /* Counter for number of epochs with intensity below the threshold. */ eoi=0; /* Indicator for end of interval */ DO i=1 TO &max_win; /* Initialize the window. */ win_obsn(i)=0; win_int(i)=0; win_flg(i)=0; END; END; RETAIN mv_num last_mv reset strt_mv end_mv start mv_cnt found stopped sum10 cnt_below eoi; RETAIN win_obsn1-win_obsn&max_win; RETAIN win_int1-win_int&max_win; RETAIN win_flg1-win_flg&max_win; /* If the intensity count is >= the threshold, start the bout. */ IF &bout_flg=1 AND start=0 THEN DO; start=1; IF mv_cnt=0 THEN last_mv=obsn; END; /* Stop or reset if obsn is not adjacent to the last obsn */ IF NOT mv_cnt EQ 0 THEN DO; IF obsn EQ last_mv + 1 THEN last_mv = obsn; ELSE IF mv_cnt<&min_win THEN reset = 1; ELSE stopped = 1; IF reset OR stopped THEN DO; eoi = 1; GOTO outputobs; END; END; /* Accumulate the counts. */ IF start=1 THEN mv_cnt=mv_cnt+1; /* Set up a moving window. */ IF 1<=mv_cnt<=&max_win AND NOT found THEN DO; win_obsn(mv_cnt)=obsn; win_int(mv_cnt)=amcount; win_flg(mv_cnt)=&bout_flg; IF amcount = . THEN reset=1; /* If a missing count is encounted before reaching the end of the window, reset and start again. */ END; /* When the end of the window is attained, count the total number of intensity counts that are >= threshold. */ IF mv_cnt=&max_win AND NOT reset THEN sum10=sum(OF win_flg1-win_flg&max_win); /* If the minimum number of epochs with intensity counts >= the threshold is attained, a bout is established. */ IF sum10>=&min_win THEN found=1; /* If the minimum number of epochs with intensity counts >= the threshold is not attained, continue to search. */ /* Move the window down, one epoch at a time. */ ELSE IF 0&max_win THEN DO; IF amcount=. then reset=1; /* If the last epoch has a missing count, reset and start again. */ ELSE DO; DO i=1 TO (&max_win - 1); win_obsn(i)=win_obsn(i+1); win_int(i)=win_int(i+1); win_flg(i)=win_flg(i+1); END; /* Read in last epoch in the window. */ win_obsn(&max_win)=obsn; win_int(&max_win)=amcount; win_flg(&max_win)=&bout_flg; sum10=sum(OF win_flg1-win_flg&max_win); END; END; IF sum10 IN (0) THEN reset=1; /* Skip windows with no valid epochs. */ /* If a bout is established. */ IF found THEN DO; /* Assign the starting epoch for the activity bout. */ IF strt_mv= 0 THEN DO; DO i=1 TO &max_win; IF win_flg(i)=1 THEN DO; /* Find the first epoch with intensity count >= the threshold. */ strt_mv=win_obsn(i); i=&max_win+1; END; END; END; /* Assign the ending epoch for the activity bout. */ IF end_mv=0 THEN DO; DO i = &max_win TO &min_win; IF win_flg(i) = 0 THEN DO; end_mv=win_obsn(i-1); cnt_below=cnt_below+1; END; END; IF end_mv=0 THEN end_mv=win_obsn(&max_win); END; IF obsn>win_obsn(&max_win) THEN DO; IF &bout_flg=1 THEN DO; cnt_below=0; end_mv=obsn; END; IF &bout_flg=0 THEN cnt_below=cnt_below+1; /* Keep track of the number of epochs with intensity counts below the threshold. */ END; /* The bout terminates if the maximum allowable number of epochs with intensities below the threshold is exceeded, or if a missing count is encountered, or if the epoch is the last one of the day. */ IF cnt_below=(&max_win - &min_win + 1) OR last.dayworn OR &bout_flg=. THEN stopped=1; END; /* Output one record for each activity bout. */ outputobs: IF stopped=1 THEN DO; dur_mv=end_mv-strt_mv+1; mv_num=mv_num+1; KEEP am_identify_no clinicid dayworn mv_num strt_mv end_mv dur_mv; OUTPUT; END; IF eoi=1 THEN GOTO resetobs; RUN; PROC SORT DATA=out&bout_flg; BY clinicid dayworn mv_num; RUN; *------------------------------------------------*; * Calculate total duration of activity bouts for *; * each day (in epoch lengths). *; *------------------------------------------------*; PROC SUMMARY DATA=out&bout_flg; BY clinicid dayworn; VAR dur_mv; OUTPUT OUT=sum_mv SUM=tot_dur_mv_brut; RUN; *------------------------------------------------*; * Output one record per day for each person in *; * the analysis (in minutes). *; *------------------------------------------------*; DATA out&bout_flg._sum; MERGE sum_all(in=in_all) sum_mv; BY clinicid dayworn; IF in_all; IF tot_dur_mv_brut=. THEN tot_dur_mv_brut=0; tot_dur_mv = tot_dur_mv_brut / &convfct; %IF &dchr=. %THEN %LET text = ; %ELSE %IF &dchr=1 %THEN %LET text = (&dc_text.); %ELSE %IF &dchr=0 %THEN %LET text = (&ndc_text.); LABEL %if &bout_flg=_pa %then %do; tot_dur_mv="Total duration (minutes) of light, moderate, or vigorous activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; %if &bout_flg=_mv %then %do; tot_dur_mv="Total duration (minutes) of moderate or vigorous activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; %if &bout_flg=_m %then %do; tot_dur_mv="Total duration (minutes) of moderate activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; %if &bout_flg=_v %then %do; tot_dur_mv="Total duration (minutes) of vigorous activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; %if &bout_flg=_sed %then %do; tot_dur_mv="Total duration (minutes) of sedentary activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; %if &bout_flg=_lt %then %do; tot_dur_mv="Total duration (minutes) of light activity bouts (&min_win out of &max_win Epochs) in a day &text" %end; ; KEEP clinicid dayworn tot_dur_mv; RENAME tot_dur_mv=tot_dur&bout_flg; RUN; %MEND bouts_8of10; /* Run the bouts_8of10 macro for each intensity using the interval specified in Code Step 3.7. */ %MACRO bouts_8of10_grp(dchr=); %bouts_8of10(bout_flg=_mv,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %bouts_8of10(bout_flg=_v,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %bouts_8of10(bout_flg=_m,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %bouts_8of10(bout_flg=_sed,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %bouts_8of10(bout_flg=_lt,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %bouts_8of10(bout_flg=_pa,convfct=&conv_epoch.,min_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_min. * &conv_epoch.))),max_win=%SYSFUNC(CEIL(%SYSEVALF(&bout_time.*&conv_epoch.))),dchr=&dchr); %MEND bouts_8of10_grp; *------------------------------------------------------------*; * Summarize the data to one record per person per day with *; * duration of non-wear and activity bouts (in minutes). *; *------------------------------------------------------------*; DATA nonwear; SET outlib.weartime; RUN; PROC SORT DATA=nonwear; BY clinicid dayworn; RUN; /* All hours */ %bouts_grp(&bout_lgth.,.); /* Run the boutsgrp macro using the value defined in Code Step 3.6. */ %bouts_8of10_grp(dchr=.); /* Run the bouts_8of10_grp macro using the value defined in Code Step 3.6 */ DATA Summary_all; MERGE nonwear(KEEP=clinicid dayworn tot_cnt_wr tot_min tot_dur_nw tot_min_wr wear_hr IN=iall) /* bouts macro variables */ out_pa&bout_lgth._sum out_mv&bout_lgth._sum out_v&bout_lgth._sum out_m&bout_lgth._sum out_lt&bout_lgth._sum out_sed&bout_lgth._sum /* bouts_8of10 macro variables */ out_pa_sum out_mv_sum out_v_sum out_m_sum out_lt_sum out_sed_sum ; BY clinicid dayworn; IF iall; RUN; /* Subset hours only */ %bouts_grp(&bout_lgth.,1); /* Run the boutsgrp macro using the value defined in Code Step 3.6. */ %bouts_8of10_grp(dchr=1); /* Run the bouts_8of10_grp macro using the value defined in Code Step 3.6 */ DATA Summary_dc; MERGE nonwear(KEEP=clinicid dayworn tot_cnt_wr_dc tot_min_dc tot_dur_nw_dc tot_min_wr_dc wear_hr_dc IN=idc) /* bouts macro variables */ out_pa&bout_lgth._sum out_mv&bout_lgth._sum out_v&bout_lgth._sum out_m&bout_lgth._sum out_lt&bout_lgth._sum out_sed&bout_lgth._sum /* bouts_8of10 macro variables */ out_pa_sum out_mv_sum out_v_sum out_m_sum out_lt_sum out_sed_sum ; BY clinicid dayworn; IF idc; RENAME /* bouts macro variables */ tot_dur_pa&bout_lgth.=tot_dur_pa&bout_lgth._dc tot_dur_mv&bout_lgth.=tot_dur_mv&bout_lgth._dc tot_dur_v&bout_lgth.=tot_dur_v&bout_lgth._dc tot_dur_m&bout_lgth.=tot_dur_m&bout_lgth._dc tot_dur_lt&bout_lgth.=tot_dur_lt&bout_lgth._dc tot_dur_sed&bout_lgth.=tot_dur_sed&bout_lgth._dc /* bouts_8of10 macro variables */ tot_dur_pa=tot_dur_pa_dc tot_dur_mv=tot_dur_mv_dc tot_dur_v=tot_dur_v_dc tot_dur_m=tot_dur_m_dc tot_dur_lt=tot_dur_lt_dc tot_dur_sed=tot_dur_sed_dc ; RUN; /* Non-subset hours only */ %bouts_grp(&bout_lgth.,0); /* Run the boutsgrp macro using the value defined in Code Step 3.6. */ %bouts_8of10_grp(dchr=0); /* Run the bouts_8of10_grp macro using the value defined in Code Step 3.6 */ DATA Summary_ndc; MERGE nonwear(KEEP=clinicid dayworn tot_cnt_wr_ndc tot_min_ndc tot_dur_nw_ndc tot_min_wr_ndc wear_hr_ndc IN=indc) /* bouts macro variables */ out_pa&bout_lgth._sum out_mv&bout_lgth._sum out_v&bout_lgth._sum out_m&bout_lgth._sum out_lt&bout_lgth._sum out_sed&bout_lgth._sum /* bouts_8of10 macro variables */ out_pa_sum out_mv_sum out_v_sum out_m_sum out_lt_sum out_sed_sum ; BY clinicid dayworn; IF indc; RENAME /* bouts macro variables */ tot_dur_pa&bout_lgth.=tot_dur_pa&bout_lgth._ndc tot_dur_mv&bout_lgth.=tot_dur_mv&bout_lgth._ndc tot_dur_v&bout_lgth.=tot_dur_v&bout_lgth._ndc tot_dur_m&bout_lgth.=tot_dur_m&bout_lgth._ndc tot_dur_lt&bout_lgth.=tot_dur_lt&bout_lgth._ndc tot_dur_sed&bout_lgth.=tot_dur_sed&bout_lgth._ndc /* bouts_8of10 macro variables */ tot_dur_pa=tot_dur_pa_ndc tot_dur_mv=tot_dur_mv_ndc tot_dur_v=tot_dur_v_ndc tot_dur_m=tot_dur_m_ndc tot_dur_lt=tot_dur_lt_ndc tot_dur_sed=tot_dur_sed_ndc ; RUN; /* Combine all summaries */ DATA Summary; MERGE dayofweek summary_all(IN=iCount) sumstep(IN=iStep) summary_dc sumstep_dc summary_ndc sumstep_ndc; BY clinicid dayworn; IF iCount AND iStep; RUN; DATA perday; SET Summary; KEEP am_identify_no clinicid dayworn dayofweek_worn /* All hours */ wear_hr tot_dur_pa&bout_lgth. tot_dur_mv&bout_lgth. tot_dur_v&bout_lgth. tot_dur_m&bout_lgth. tot_dur_lt&bout_lgth. tot_dur_sed&bout_lgth. tot_cnt_wr tot_dur_pa tot_dur_mv tot_dur_v tot_dur_m tot_dur_lt tot_dur_sed amstep /* Subset hours only */ wear_hr_dc tot_dur_pa&bout_lgth._dc tot_dur_mv&bout_lgth._dc tot_dur_v&bout_lgth._dc tot_dur_m&bout_lgth._dc tot_dur_lt&bout_lgth._dc tot_dur_sed&bout_lgth._dc tot_cnt_wr_dc tot_dur_pa_dc tot_dur_mv_dc tot_dur_v_dc tot_dur_m_dc tot_dur_lt_dc tot_dur_sed_dc amstep_dc /* Non-subset hours only */ wear_hr_ndc tot_dur_lt&bout_lgth._ndc tot_dur_m&bout_lgth._ndc tot_dur_v&bout_lgth._ndc tot_dur_mv&bout_lgth._ndc tot_dur_pa&bout_lgth._ndc tot_dur_sed&bout_lgth._ndc tot_cnt_wr_ndc tot_dur_pa_ndc tot_dur_mv_ndc tot_dur_v_ndc tot_dur_m_ndc tot_dur_lt_ndc tot_dur_sed_ndc amstep_ndc ; LABEL am_identify_no = "File" clinicid = "ID" dayworn = "Day" dayofweek_worn = "Day of the week" amstep = "Step count" amstep_dc = "Step count (&dc_text)" amstep_ndc = "Step count (&ndc_text)" ; RUN; /* Save the output dataset. */ DATA outlib.perday; SET perday; RUN; /* Export the results as an Excel spreadsheet. */ PROC EXPORT DATA = perday OUTFILE = "&xls_path." REPLACE; RUN; *-----------------------------------------------------------------------------------------------*; * THIS CODE ENDS WITH A DATAFILE CALLED "PERDAY" TO BE READ INTO CODE STEP 4. *; *-----------------------------------------------------------------------------------------------*;