Thursday
Quentin
Super User
Member since
06-23-2011
- 3,756 Posts
- 2,517 Likes Given
- 318 Solutions
- 2,498 Likes Received
-
Latest posts by Quentin
Subject Views Posted 182 a week ago 526 2 weeks ago 255 3 weeks ago 745 3 weeks ago 753 3 weeks ago 1492 3 weeks ago 754 4 weeks ago 2528 4 weeks ago 425 4 weeks ago 1340 a month ago -
Activity Feed for Quentin
- Liked Re: Adding a new variable but the labels of the previous datasets are not kept. how to solve that is for Tom. Tuesday
- Got a Like for Re: Thoughts on building experience as professional SAS programmer & finding entry-level job?. a week ago
- Got a Like for Re: Proc Compare - OUTDIFF filter on difference value. a week ago
- Got a Like for Re: Proc Compare - OUTDIFF filter on difference value. a week ago
- Posted Re: Proc Compare - OUTDIFF filter on difference value on SAS Programming. a week ago
- Posted Re: SAS Logs from LSF Scheduled jobs on Administration and Deployment. 2 weeks ago
- Liked Re: How to extract file information on a web server for ChrisHemedinger. 2 weeks ago
- Posted Re: Join a table with another in long format by two variables on New SAS User. 3 weeks ago
- Liked Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf for Tom. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 3 weeks ago
- Posted Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf on Advanced Programming. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 3 weeks ago
- Posted Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf on Advanced Programming. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 3 weeks ago
- Posted Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf on Advanced Programming. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 3 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 4 weeks ago
- Posted Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf on Advanced Programming. 4 weeks ago
- Got a Like for Re: Another way(and simpler) to solve practice question m104p11 on page 224 ,Macro1: Essentials pdf. 4 weeks ago
-
-
My Liked Posts
Subject Likes Posted 2 a week ago 3 3 weeks ago 1 3 weeks ago 1 3 weeks ago 1 4 weeks ago
a week ago
2 Likes
The E is a SAS Special Missing Value. You can refer to it like:
IF column = .E then ... ;
The special missing values (._ .A to .Z) can be used to distinguish different reasons that a value might be missing. For example, in a survey, you might have "Don't Know", "Refused", "Skipped" etc.
... View more
2 weeks ago
I don't know a way for the executing batch job to know the name of its log file. I'm sure that has been wanted by many people for many years, but I don't remember ever having it. I've always had to deduce the name of the log file (from the program name etc.). One (ugly) work around is for your job to use PROC PRINTTO to write the log a new file. If your job is responsible for creating the log file (rather than using the log file created by the shell script), it will know the name of the log file. Typically in my jobs I will start with a PRINTTO step that sends my log to a file I create, in the same directory that admins chose for the log files. This way I can process the log at the end, without worrying about the log naming scheme used by the admins. But as I say, it feels like a hack. For example, the log file is not the *full* log file from the job, it's only the log file from my code.
... View more
3 weeks ago
Can you show the code you have tried? Curious if you tried a DATA step merge, or SQL approach? It will help people help you to see the code you have tried, along with an explanation whether you are getting errors from your code, or unexpected results.
... View more
3 weeks ago
3 Likes
The issue of macro variable scope is a tricky one, and worth working through.
You asked for a brief explanation why the %LOCAL statement should almost always be used to define macro variables as %local to a macro. I would say:
Suppose I'm a macro user. And in my SAS session I have some global macro variables that I created for my own work.
I call a macro, %storms() .
I don't expect the macro storms to change the value of any of my global macro variables, they belong to me, not the macro.
If the author of the the macro %storms() did not use the %local statement to define macro variables as %local, then the macro storms might change the value of my global macro variables. And as a user of the macro, there is no way for me to prevent that from happening.
The issue is not necessarily whether the macro itself works, it's instead a side-effect problem of the macro changing something that doesn't belong to the macro.
Consider this macro without a local statement, which just writes the items in a list to the log:
%macro withoutlocal(list);
%let count=%sysfunc(countw(&list));
%do i=1 %to &count;
%let yr=%scan(&list,&i);
%put &=yr ;
%end;
%put _user_ ;
%mend withoutlocal;
If I call that macro:
%withoutlocal(A B C)
it works. And the macro variables COUNT, I, and YR will all be created as local macro variables. I added a %PUT _USER_ statement to show this:
197 %withoutlocal(A B C)
YR=A
YR=B
YR=C
WITHOUTLOCAL COUNT 3
WITHOUTLOCAL I 4
WITHOUTLOCAL LIST A B C
WITHOUTLOCAL YR C
However, suppose I create a global macro variable named count, which I want to use in my program for some purpose unrelated to the macro. And then suppose I call the macro.
%let count=100;
%withoutlocal(A B C)
%put &=count;
Now the log shows that instead of creating a local macro variable named COUNT, the macro used *my* global macro variable count. The macro "worked" in terms of returning the items of the list. But after the macro has run, my macro variable COUNT has the wrong value, because the macro wrote the value 3 to my macro variable, instead of creating its own macro variable:
198 %let count=100;
199 %withoutlocal(A B C)
YR=A
YR=B
YR=C
WITHOUTLOCAL I 4
WITHOUTLOCAL LIST A B C
WITHOUTLOCAL YR C
GLOBAL COUNT 3
200 %put &=count;
COUNT=3
As a user of a macro, I can't prevent the macro from accidentally changing my macro variables, if I happen to have macro variables that have the same name as macro variables used in the macro. I rely on the macro author to be conscientious enough to declare all the macro variables to be %local, to prevent "collisions" with my macro variables.
The general guideline for writing macro is when you create a macro variable, always use the %LOCAL statement to create them as local to the macro, unless you have a really really good reason not to do so. To protect your users (and yourself) from collisions.
... View more
3 weeks ago
1 Like
@dxiao2017 wrote:
Is this (see below) what you and Tom want me to try? Without the %local statement: got a warning message (&count cannot resolve) and something massed up with the report title(the 2011 one becomes 2014, which is not correct):
%macro storms(list);
*%local count i yr;
%let count=%sysfunc(countw(&list));
%do i=1 %to &count;
%let yr=%scan(&list,&i);
title "&yr Storms";
proc means data=mc1.storm_final n min
mean max maxdec=0;
var MaxWindMPH MinPressure;
where season=&yr;
run;
%end;
%mend storms;
%storms(2011 2012 2014);
There is a small mistake in that example you wrote. You tried to comment out the %LOCALstatement with:
*%local count i yr;
But the * is not a comment in the macro language. That %LOCAL statement will still be executed.
To comment it out, you need a macro comment, either %* or /* */ . So you could comment it out with:
%*local count i yr;
I'll write more in another post.
... View more
3 weeks ago
1 Like
As your post showed, when you run:
%let count=100;
%storms(2011 2012 2014)
%put &count;
If your macro storms uses the %local statement to create a new local macro variable COUNT, the %PUT statement at the end will show that the global macro variable COUNT still has the value 100. Now if you remove the %local statement from your macro definition and recompile the macro, then run the same code, the %PUT statement at the end will show that the global macro variable COUNT has a different value. Please try it out.
... View more
4 weeks ago
1 Like
@quickbluefish wrote:
Agree with others here - I would just add that with COUNTW and SCAN (and similar), it's a good idea to specify your delimiter as the optional last argument - otherwise, SAS will try to guess. And further, if the delimiter is a space (as it is here), never a bad idea to clean up potential multiple whitespace characters with %CMPRES:
%let YRLIST=2012 2014 2016;
%let YRLIST=%CMPRES(&YRLIST);
%let nYRS=%sysfunc(countW(&YRLIST,' '));
.... %let YR=%SCAN(&YRLIST, &i, ' ');
* you can also use %STR( ) instead of ' ' above ;
I agree it's good practice to specify the delimiter for COUNTW and %SCAN. Particularly because if you have an empty list, %sysfunc(countw()) will throw an error, but %sysfunc(countw(,%str( ))) will return 0.
That said, I think it's much clearer/better to use %STR( ) to specify the blank as delimiter, rather than ' '. If you use ' ' you're telling the macro processor to use both blank and a single quote as delimiters. In the macro language ' ' is a three character string, not a single blank.
... View more
4 weeks ago
3 Likes
That shown style of looping over a list with %DO %UNTIL was common prior to the introduction of the COUNTW function. I think COUNTW was introduced in v7 or v8.
I would agree that using COUNTW to count the number of items in a list seems clearer to me also.
... View more
4 weeks ago
Can you post the code you use to create the .csv?
Can you run PROC CONTENTS on the M7 dataset and the M8 dataset to see if they have different formats attached to your date-time variables?
... View more
a month ago
Can you post the code you are using to import one .png to an rtf file?
If you have that code working, then there are plenty of macros that can give you a list of all .png files in a directory. e.g.:
https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/mcrolref/n0js70lrkxo6uvn1fl4a5aafnlgt.htm
So if you have working code for one .png file, you could use a macro to loop over a list of .png files.
... View more
02-11-2025
10:36 AM
5 Likes
That's odd. If your goal is to get rid of the whiskers, you could try:
whiskerattrs=(thickness=0)
Suggestion taken from:
https://communities.sas.com/t5/Graphics-Programming/Creating-a-boxplot-without-whiskers/td-p/248745
... View more
02-10-2025
06:12 PM
3 Likes
I think it all depends on your axis. For series plots the x-axis is typically continuous, so you can do a bit of jittering. But for box plots, the x-axis is categorical. So if you do the jittering and specify values for the x-axis, you would need to specify jittered values on the x axis.
... View more
02-10-2025
02:11 PM
In the DATA step you manually introduced jitter in the values of VIS.
In the XAXIS statement you specified the values to be plotted:
values=(0,1,2,3,4,6,8,10,12,16,20,24,28,32,36,40,44,48,52 )
My guess is after you jitter the data, those values don't appear in your data.
... View more
02-10-2025
02:05 PM
If you comment out the xaxis statement, do you get boxes?
If you comment out yaxis statement?
I wonder if the values you entered on the xaxis statement are not the actual values in your dataset. Or if your values are outside the yaxis.
One thing I don't like about SGPLOT vs the much older traditional GPLOT is that SGPLOT does not throw a NOTE when you have data outside of your axes. It's possible all your data is outside the axes.
You didn't show your MYATTR dataset. Could it be everything is set to transparent? I would suggest start with a working plot that is simple, maybe:
proc sgplot data=ip ;
vbox aval1 / category=vis group=param1 nomean nooutliers whiskerpct=25
connect=median lineattrs=( pattern=1) attrid=param1;
run;
And then add back more of your real code incrementally, until the boxes disappear.
... View more
02-08-2025
03:27 PM
Instead of using SGPANEL, you could use SGPLOT with a BY statement, that will make one histogram per by-group.
... View more