Hi
As a first step in creating a forest plot I need to read my datalines in. This does not work, however.
The code was found at pharmasug.org and the data shown here are also from the code on the original website. I get the same results if I run the code with their data or my own data. See the code below. Error message and output can be seen in the attached file.
Any insights into what might cause the problem would be greatly appreciated!
Kind regard,
Asger
%let dpi=300; %let w=9in; %let h=6.5in; data SubgroupData; input Indent Subgroup $3-27 CountA EventA CountB EventB HR CIL CIU PValue; format HR CIL CIU PValue 7.2 CountA EventA CountB EventB 5. PctA PctB 4.1; format EventDisplayA CountDisplayA EventDisplayB CountDisplayB $4. ; if CountA ne . then do; PctA = (EventA/CountA)*100; PctB = (EventB/CountB)*100; EventDisplayA = right(put(EventA, 4.0)); CountDisplayA = left(put(CountA, 4.0)); EventCountA = right(EventDisplayA || "/" || CountDisplayA); PctDisplayA = "(" || put(PctA, 4.1) || ")"; EventDisplayB = right(put(EventB, 4.0)); CountDisplayB = left(put(CountB, 4.0)); EventCountB = right(EventDisplayB || "/" || CountDisplayB); PctDisplayB = "(" || put(PctB, 4.1) || ")"; HRCI = put(HR, 4.2) || " (" || put(CIL, 4.2) || ", " || put(CIU, 4.2) || ")"; /* Determine the marker size based on population size */ SquareSize = ((CountA + CountB)/3876) * 12 ; end; row = _n_; datalines; 0 Age . . . . . . . 0.72 1 < 65 Yr 1077 81 1091 111 0.73 0.55 0.97 . 1 >= 65 Yr 862 94 846 117 0.79 0.60 1.03 . 0 Gender . . . . . . . 0.30 1 Male 1293 126 1245 147 0.81 0.64 1.03 . 1 Female 646 49 692 81 0.65 0.46 0.93 . How to Create a Journal Quality Forest Plot with SAS® 9.4, continued 8 0 Race . . . . . . . 0.75 1 White 1600 144 1619 189 0.77 0.62 0.95 . 1 Black or African American 218 22 225 32 0.67 0.39 1.16 . 1 Other 88 8 60 5 1.08 0.35 3.29 . 0 Ethnicity . . . . . . . 0.51 1 Hispanic 75 7 72 12 0.58 0.23 1.46 . 1 Non-Hispanic 1852 168 1857 215 0.78 0.63 0.95 . 0 Body Mass Index . . . . . . . 0.14 1 < 30 1123 99 1096 142 0.67 0.52 0.87 . 1 >= 30 810 75 835 85 0.91 0.67 1.24 .
You can make this work by adding an extra space in the data after the subgroup name, and using an ampersand in list input, this way:
data SubgroupData;
input Indent Subgroup &$25. CountA EventA CountB EventB HR CIL CIU PValue;
format HR CIL CIU PValue 7.2 CountA EventA CountB EventB 5. PctA PctB 4.1;
format EventDisplayA CountDisplayA EventDisplayB CountDisplayB $4. ;
if CountA ne . then do;
PctA = (EventA/CountA)*100;
PctB = (EventB/CountB)*100;
EventDisplayA = right(put(EventA, 4.0));
CountDisplayA = left(put(CountA, 4.0));
EventCountA = right(EventDisplayA || "/" || CountDisplayA);
PctDisplayA = "(" || put(PctA, 4.1) || ")";
EventDisplayB = right(put(EventB, 4.0));
CountDisplayB = left(put(CountB, 4.0));
EventCountB = right(EventDisplayB || "/" || CountDisplayB);
PctDisplayB = "(" || put(PctB, 4.1) || ")";
HRCI = put(HR, 4.2) || " (" || put(CIL, 4.2) || ", "
|| put(CIU, 4.2) || ")";
/* Determine the marker size based on population size */
SquareSize = ((CountA + CountB)/3876) * 12 ;
end;
row = _n_;
datalines;
0 Age . . . . . . . 0.72
1 < 65 Yr 1077 81 1091 111 0.73 0.55 0.97 .
1 >= 65 Yr 862 94 846 117 0.79 0.60 1.03 .
0 Gender . . . . . . . 0.30
1 Male 1293 126 1245 147 0.81 0.64 1.03 .
1 Female 646 49 692 81 0.65 0.46 0.93 .
0 Race . . . . . . . 0.75
1 White 1600 144 1619 189 0.77 0.62 0.95 .
1 Black or African American 218 22 225 32 0.67 0.39 1.16 .
1 Other 88 8 60 5 1.08 0.35 3.29 .
0 Ethnicity . . . . . . . 0.51
1 Hispanic 75 7 72 12 0.58 0.23 1.46 .
1 Non-Hispanic 1852 168 1857 215 0.78 0.63 0.95 .
0 Body Mass Index . . . . . . . 0.14
1 < 30 1123 99 1096 142 0.67 0.52 0.87 .
1 >= 30 810 75 835 85 0.91 0.67 1.24 .
;
The position you use for subgroup won't work, as the values have different width. I suggest you use a delimiter other than blank, so you can use list input without positions.
You can make this work by adding an extra space in the data after the subgroup name, and using an ampersand in list input, this way:
data SubgroupData;
input Indent Subgroup &$25. CountA EventA CountB EventB HR CIL CIU PValue;
format HR CIL CIU PValue 7.2 CountA EventA CountB EventB 5. PctA PctB 4.1;
format EventDisplayA CountDisplayA EventDisplayB CountDisplayB $4. ;
if CountA ne . then do;
PctA = (EventA/CountA)*100;
PctB = (EventB/CountB)*100;
EventDisplayA = right(put(EventA, 4.0));
CountDisplayA = left(put(CountA, 4.0));
EventCountA = right(EventDisplayA || "/" || CountDisplayA);
PctDisplayA = "(" || put(PctA, 4.1) || ")";
EventDisplayB = right(put(EventB, 4.0));
CountDisplayB = left(put(CountB, 4.0));
EventCountB = right(EventDisplayB || "/" || CountDisplayB);
PctDisplayB = "(" || put(PctB, 4.1) || ")";
HRCI = put(HR, 4.2) || " (" || put(CIL, 4.2) || ", "
|| put(CIU, 4.2) || ")";
/* Determine the marker size based on population size */
SquareSize = ((CountA + CountB)/3876) * 12 ;
end;
row = _n_;
datalines;
0 Age . . . . . . . 0.72
1 < 65 Yr 1077 81 1091 111 0.73 0.55 0.97 .
1 >= 65 Yr 862 94 846 117 0.79 0.60 1.03 .
0 Gender . . . . . . . 0.30
1 Male 1293 126 1245 147 0.81 0.64 1.03 .
1 Female 646 49 692 81 0.65 0.46 0.93 .
0 Race . . . . . . . 0.75
1 White 1600 144 1619 189 0.77 0.62 0.95 .
1 Black or African American 218 22 225 32 0.67 0.39 1.16 .
1 Other 88 8 60 5 1.08 0.35 3.29 .
0 Ethnicity . . . . . . . 0.51
1 Hispanic 75 7 72 12 0.58 0.23 1.46 .
1 Non-Hispanic 1852 168 1857 215 0.78 0.63 0.95 .
0 Body Mass Index . . . . . . . 0.14
1 < 30 1123 99 1096 142 0.67 0.52 0.87 .
1 >= 30 810 75 835 85 0.91 0.67 1.24 .
;
Thank you both. It now works after having removed $3-27 and replaced it by &$25 and used doubble spacing.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.