Skip to content

Answers, Part I

Every answer below was checked by running the code on SAS OnDemand with the pilot data.

1-1. 143 women (56.30%) and 111 men (43.70%).

1-2. Write IF age > 80 THEN agegrp = "over 80"; ELSE agegrp = "80 or less";. 77 subjects are older than 80. The other 177 are 80 or younger.

1-3. Without DESCENDING, the first record of each arm is the youngest subject: age 52 on placebo, 56 on the high dose and 51 on the low dose.

1-4. Placebo 5, Xanomeline High Dose 8, Xanomeline Low Dose 16 subjects. They have 6, 10 and 25 severe events.

1-5. N 84, mean 75.7, the oldest is 88.0 (the youngest 51.0).

1-6. The date of first study treatment is collected in EX (variable EXSTDTC, ISO 8601 text). In ADSL it is TRTSDT, a SAS date.

1-7. It breaks “one PROC away”. A table program should only select, count and print. Change from baseline (CHG) belongs in the BDS data set (chapter 10).

1-8. For example: “DM holds all 306 subjects who signed consent. 52 were screen failures and were never randomised, so ADSL keeps the 254 randomised subjects.”

2-1. Use WHERE armcd = "Pbo";. The log says NOTE: The data set WORK.DM_RAND has 86 observations.

2-2. At the top of every loop, n is missing (.). An assignment creates it, so SAS resets it before each record. It gets the value of _N_ only after the SET.

2-3. ERROR: Variable age_months is not on file REFADM.ADSL. A WHERE sees only the variables of the input data set.

2-4. 2. DIABP has 2 missing values, and both are less than 140 for SAS.

2-5. The last line has only 3 values, so INPUT goes to the next line for the fourth. It finds the end of the data. The log says NOTE: LOST CARD. and NOTE: SAS went to a new line when INPUT statement reached past the end of a line. Week 26 is lost: the data set has 8 rows instead of 9.

2-6. The header line becomes a data row: avisit is “avisit” and the four numbers are missing. The log has NOTE: Invalid data for avisitn in line 1 8-14. and the same NOTE for awlo, awtarget and awhi. The data set has 10 rows instead of 9.

2-7. Add after the imputation: IF NOT MISSING(adtf) AND aendt > "31MAR2014"d THEN aendt = "31MAR2014"d;. Only the row 2014 changes: its late date 31DEC2014 becomes 31MAR2014. The row 2014-03 already ends on 31MAR2014. The collected dates (adtf blank) do not change.

2-8. Remove the line with weight and height (DM has no such variables), and convert on purpose: siteid_num = INPUT(siteid, 8.);. The log then shows NOTE: The data set WORK.LOG_FIXED has 3 observations, and the Suspicious Log is empty.

3-1. With the ELSE text first in the code, the first use has 11 characters, so agegrp gets length 11. All three rows are correct. The program is still fragile, because the length depends on the order of the lines. Use ATTRIB or LENGTH.

3-2. The LABEL statement wins: the label is “Age group (years)”. The last statement that sets an attribute decides.

3-3. Yes. INPUT(age_c, 3.) converts on purpose, so SAS writes no “converted” NOTE.

3-4. 33, the same as with AEDECOD. In the pilot data, the same 33 records have “pain” in both variables.

3-5. 8 subjects have 11 start dates with only the year: 01-701-1118, 01-701-1180, 01-701-1363 (2), 01-703-1076, 01-703-1258 (2), 01-703-1299, 01-710-1077 (2) and 01-718-1355.

3-6. The 4 records are two events of 01-716-1418, HEADACHE (01JUL2013 to 26SEP2013) and VISION BLURRED (01JUL2013 to 04OCT2013), each twice. ASTDTF is D: the start day was imputed. The reference computes no duration from an imputed start date. The formula aendt - astdt + 1 does. Which one is right is a decision for the specification.

3-7. (a + b + c) / 3 is missing, and the log gets the NOTE “Missing values were generated”. MEAN(a, b, c) ignores the missing value and gives 2.

3-8. VVALUE returns the number as text, right-aligned in the width of the format: " 99". Compare STRIP(VVALUE(trt01pn)) with CATS(trt01pn). When they are equal, the code is not in the format. Write a WAR/NING message in that case.

4-1. 609 records are deleted (NOTE: 609 observations with duplicate key values were deleted.).

4-2. Without the reset, n_ae goes on from 3: subject 01-701-1023 gets n_ae = 7 instead of 4.

4-3. pchg = chg / base * 100; Check that base is not missing and not 0 before you divide, or SAS writes a “Division by zero” NOTE.

4-4. In the pilot data, aeser is never missing, so the new data set has 0 records, and 3 + 1188 + 0 = 1191 still holds. Keep the branch anyway: it proves that the program handles the case.

5-1. IF inae AND NOT indm THEN OUTPUT ae_only; gives one record: S5, RASH.

5-2. With ORDER BY usubjid, aedecod, the S4 rows come as DIZZINESS, then NAUSEA.

5-3. MERGE dm(IN=indm) ae; BY usubjid; IF indm; gives the same five rows as the left join: S1, S2 HEADACHE, S3, S4 DIZZINESS, S4 NAUSEA. Only the order of the two S4 rows can differ, because SQL promises no order.

5-4. 29 subjects: SELECT COUNT(*) FROM refadm.adsl WHERE usubjid NOT IN (SELECT usubjid FROM refadm.adae);

6-1. Add AND trt01a = "Placebo" to the WHERE: WHERE saffl = "Y" AND trt01a = "Placebo";. The fifth placebo subject is 01-701-1130 (the first four are 01-701-1015, 01-701-1023, 01-701-1047 and 01-701-1118).

6-2. TABLES trt01a * race / LIST NOCUM; gives 78 White subjects in the placebo arm (and 8 Black or African American).

6-3. 10 records: one for all subjects (_TYPE_ = 0), three for TRT01A alone, three for TRT01AN alone and three for both. The mean age of all 254 subjects is 75.1 (75.0866).

6-4. Only Placebo (86) stays: the other two groups have 84.

6-5. With trtemfl = "Y" AND aeser = "Y" in the WHERE= of ADAE: 0 subjects on placebo, 1 on the low dose, 2 on the high dose.

6-6. bign becomes the number of subjects with a TEAE: 65, 77 and 76, the same as n_teae, so every percentage is 100.

6-7. 19 subjects: SELECT usubjid FROM cm_subj EXCEPT SELECT usubjid FROM ae_subj (229 subjects with a medication minus the 210 with both).

6-8. SELECT memname INTO :domains SEPARATED BY " " FROM dictionary.tables WHERE libname = "SDTM"; gives AE CM DM DS EX LB MH SUPPDM SV VS.

7-1. comp8fn sums to 190 and comp16fn to 147.

7-2. ERROR: Unsatisfied WHEN clause and no OTHERWISE clause, and the step stops at the first record: WORK.TRT_GROUP has 0 records (SAS writes a WARNING that the data set may be incomplete). With OTHERWISE, the record gets “Unknown” and the step goes on.

7-3. ERROR: The ID value "DIABPbl" occurs twice in the same BY group. Each subject has three baseline records per test, one per position, so one ID value would need three values in the same row.

7-4. Nine value columns, one per test and position. SAS builds the names from both ID values, for example 'DIABPAFTER LYING DOWN FOR 5 MINU'n: cut at 32 characters and written as a name literal. Clear names are one more reason to choose one position before you transpose.

7-5. VALUE sevf 1 = "MILD" 2 = "MODERATE" 3 = "SEVERE"; and FORMAT aesevn sevf.; in the PROC FREQ. The table shows the texts MILD 770, MODERATE 378, SEVERE 43, in the order of the numbers, not of the alphabet: PROC FREQ sorts by the stored value.

7-6. The table shows the treatment names instead of the codes: Placebo 301, Xanomeline Low Dose 435, Xanomeline High Dose 455 records.

7-7. 8437 VS records belong to subjects older than 80.

8-1. &lib.&ds. resolves to refadmadsl, a one-level name in WORK: ERROR: File WORK.REFADMADSL.DATA does not exist.

8-2. 126 of the 143 female subjects are White (88.11%).

8-3. NOTE: after the call WHERE=outer. Without %LOCAL, the %LET in %outer finds the existing global where and changes it.

8-4. _CB_001_IN stays in WORK, because debug=Y skips the cleanup.