BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
DDT
Obsidian | Level 7 DDT
Obsidian | Level 7

This is a continuation of my GTL Box plot learning curve 🙂 I have Win64 SAS 9.4 M2.

 

Working with the code, below, I can easily get either zero or multiple reference line(s) to display. For example, use _REFLINES="0,9" in the code, below, instead of _REFLINES="100". But I cannot get exactly 1 reference line, e.g., 100, to conditionally appear.

 

I am trying to:

Specifying exactly 1 reference line does not work, and seems to fail because the EVAL(LENGTH(_REFLINES)) return value is missing when _REFLINES contains only digits. Note that I have printed the result of this evaluation in the graph title.

 

Without a proper result from eval(length()), it's hard to program around using COLN() or a single value.

I've tried searching these communities, as well as SAS Notes.

 

Notable behavior, the same whether I use LENGTH() or LENGTHC():

  • EVAL(LENGTH(_REFLINES)) is missing, zero-length, for _REFLINES="100". Check the title text.
  • _REFLINES="100" works as expected with COLN(), if I remove the conditional code IF EVAL(LENGTH(_REFLINES) > 0) and ENDIF;.
  • Use _REFLINES="100 a" in the code, below, instead of _REFLINES="100". and I magically get the 100 line, a correct length of 5, and no syntax warning or error (but COLN() does not like "100,a").
  • Use _REFLINES="100  " (trailing blanks) in the code, below, and change LENGTH() to LENGTHC() which should not strip trailing blanks, but the single reference line is still omitted, and the length() in the title is still null.
  • _REFLINES="100 110" produces errors, just to confirm that COLN() expects comma-delimited values.

Are there some known problems with EVAL(LENGTH(...)) or fixes in SAS 9.4 after M2?

Must the string to test include some non-digit, non-space character (a bit unexpected to me)?

 

Here's the play code, and thanks for any advice or alternate approach:

 

      proc template;
        define statgraph xalignedstats;
          dynamic _GRP _CAT _MEASURE _REFLINES;

          begingraph / border=false dataskin=none;
            entrytitle 'Check result of eval(length(_REFLINES)) [' EVAL(LENGTH(_REFLINES)) ']';
            layout overlay / walldisplay=none xaxisopts=(discreteopts=(tickvaluefitpolicy=split));
              boxplot x=_CAT y=_MEASURE / group=_GRP groupdisplay=cluster;

              IF (length(_REFLINES) > 0)

                referenceline y=eval(coln(_REFLINES)) / lineattrs=(color=red);

              ENDIF;
endlayout; endgraph; end; run; proc sgrender data=sashelp.heart template=xalignedstats; dynamic _GRP ='bp_status' _CAT ='smoking_status' _MEASURE ='diastolic' _REFLINES="100" ; run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Can you not use the exists() function on the _REFLINES variable?  The below works fine on mine:

proc template;
  define statgraph xalignedstats;
  dynamic _GRP _CAT _MEASURE _REFLINES;
  begingraph / border=false dataskin=none;
  entrytitle 'Check result of eval(length(_REFLINES)) [' EVAL(LENGTH(_REFLINES)) ']';
  layout overlay / walldisplay=none xaxisopts=(discreteopts=(tickvaluefitpolicy=split));
    boxplot x=_CAT y=_MEASURE / group=_GRP groupdisplay=cluster;
    IF (exists(_REFLINES) > 0)
      referenceline y=eval(coln(_REFLINES)) / lineattrs=(color=red);
    ENDIF;
  endlayout;
  endgraph;
  end;
run;

proc sgrender data=sashelp.heart template=xalignedstats;
  dynamic 
  _GRP     ='bp_status'
  _CAT     ='smoking_status' 
  _MEASURE ='diastolic'
  _REFLINES="100";
run;

View solution in original post

4 REPLIES 4
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Can you not use the exists() function on the _REFLINES variable?  The below works fine on mine:

proc template;
  define statgraph xalignedstats;
  dynamic _GRP _CAT _MEASURE _REFLINES;
  begingraph / border=false dataskin=none;
  entrytitle 'Check result of eval(length(_REFLINES)) [' EVAL(LENGTH(_REFLINES)) ']';
  layout overlay / walldisplay=none xaxisopts=(discreteopts=(tickvaluefitpolicy=split));
    boxplot x=_CAT y=_MEASURE / group=_GRP groupdisplay=cluster;
    IF (exists(_REFLINES) > 0)
      referenceline y=eval(coln(_REFLINES)) / lineattrs=(color=red);
    ENDIF;
  endlayout;
  endgraph;
  end;
run;

proc sgrender data=sashelp.heart template=xalignedstats;
  dynamic 
  _GRP     ='bp_status'
  _CAT     ='smoking_status' 
  _MEASURE ='diastolic'
  _REFLINES="100";
run;
DDT
Obsidian | Level 7 DDT
Obsidian | Level 7

Indeed, exists() does allow zero, 1 or multiple values! Although I cannot say that this works as I would expect 🙂

 

I did not expect EXISTS() to return zero when _REFLINES has a value that resolves to null -- e.g., pass in "&ref_lines" that resolves to "". According to EXISTS() documentation: "If item is a dynamic / macro variable, then it tests whether there has been a run-time initialization of the variable."

 

I expected that setting _REFLINES="&ref_lines" nonetheless counts as run-time initialization, even if &ref_lines resolves to a null string. I expected EXISTS("") to return 1, but LENGTH("") to return 0. So I didn't consider using EXISTS(). Lesson learned. And thanks for a solution!

DDT
Obsidian | Level 7 DDT
Obsidian | Level 7
And of course, not to overlook what still troubles me:

I don't understand why EVAL(LENGTH("100")) returns a null value...
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Yes, to be honest I am not sure why that doesn't work. It looks valid, but I rarely use conditionals in templates as there isnt a debugger for them, it would be a good feature if you could put this type of thing to the log to see what the condition being evaluated is, could it be that the eval in this instance is called with the text 'length("100,110")' so its not call the function just evaluating certain characters.  I don't know I am afraid, good question to put to tech support.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1572 views
  • 3 likes
  • 2 in conversation