The post Where does Girl Scout cookie money go? appeared first on SAS Learning Post.
]]>This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
Here in the US, it’s Girl Scout cookie season. This is when you get to spend a few bucks on cookies, break your New Year’s resolution about losing weight … and feel good about it, because the money’s going to a good cause. Or is it? – Let’s break down […]
The post Where does Girl Scout cookie money go? appeared first on SAS Learning Post.
This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
The post Solve mixedinteger linear programming problems in SAS appeared first on The DO Loop.
]]>This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
This article shows how to solve mixedinteger linear programming (MILP) problems in SAS. In a mixedinteger problem, some of the variables in the problem are integervalued whereas others are continuous. The objective function is a linear function of the variables and the variables can be subject to linear constraints.
Last month I discussed how to solve linear programming (LP) problems in SAS by using PROC OPTMODEL in SAS/OR or by using SAS/IML software.
You can use these same tools to solve mixedinteger linear programming problems.
The OPTMODEL procedure has the simpler syntax.
The MILPSOLVE function in SAS/IML software provides similar functionality in a n interactive matrix language.
The previous article solved a twovariable LP problem. If you constrain one of the variables to be an integer, you get a MILP problem, as follows:
The graph shows the feasible region. The interior of the polygon satisfies the constraints. Because x1 must be an integer, the vertical stripes indicate the feasible values of the variables. The color of the stripes indicate the value of the objective function. The green star indicates the optimal solution, which is
x = {5, 3.1}.
The following statements show one way to formulate and solve the MILP problem by using the OPTMODEL procedure in SAS/OR software:
proc optmodel; var x1 integer >= 0; /* information about the variables */ var x2 >= 0; max z = 3*x1 + 5*x2; /* define the objective function */ con c1: 3*x1 + 2*x2 <= 10; /* specify linear constraints */ con c2: 5*x1 + 10*x2 <= 56; con c3: 4*x1 + 2*x2 >= 7; solve with milp; /* solve the MILP problem */ print x1 x2; quit; 
The OPTMODEL procedure prints two tables. The first (not shown) describes the optimization algorithm and tells you that the optimal objective value is 30.5. The second table is the solution vector, which is
x = {5, 3.1}.
The MILPSOLVE subroutine in the
SAS/IML language uses matrices and vectors to specify the problem. The syntax for the MILPSOLVE subroutine is almost identical to the syntax for the LPSOLVE subroutine, so see the previous article for an explanation of each argument.
The following SAS/IML program defines and solves the MILP problem:
proc iml; /* information about variables (row of column, doesn't matter) */ colType = {I, C}; /* C, B, or I for cont, binary, int */ LowerB = {0, 0}; /* lower bound constraints on x */ UpperB = {10,10}; /* upper bound constraints on x */ /* objective function */ c = {3 5}; /* vector for objective function c*x */ /* linear constraints */ A = {3 2, /* matrix of constraint coefficients */ 5 10, 4 2}; b = {10, /* RHS of constraint eqns (column vector) */ 56, 7}; /* specify symbols for constraints: 'L' for less than or equal 'E' for equal 'G' for greater than or equal */ LEG = {L, L, G}; /* control vector for optimization */ ctrl = {1, /* maximize objective */ 1}; /* print level */ CALL MILPSOLVE(rc, objVal, result, relgap, /* output variables */ c, A, b, /* objective and linear constraints */ ctrl, /* control vector */ coltype, LEG, /*range*/, LowerB, UpperB); print rc objVal, result[rowname={x1 x2}]; 
In the call to MILPSOLVE, the first four arguments are output arguments. The return code (rc) is 0, which indicates that an optimal value was found.
The value of the objective function at the optimal value is returned in objVal.
The optimal values of the variables are returned in the result argument.
The MILPSOLVE subroutine was introduced in SAS/IML 13.1, which was shipped with SAS 9.4m1.
For additional details about the MILPSOLVE subroutine, see the documentation.
The post Solve mixedinteger linear programming problems in SAS appeared first on The DO Loop.
This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
The post Prius isn't the highestmpg hybrid in 2017! appeared first on SAS Learning Post.
]]>This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
For many years, the Toyota Prius was the hybrid with the best mpg – but in 2017 that’s changing! Let’s examine the data … For analyses like this, I have found the fueleconomy.gov website to be a wonderful source of information. In recent years, they’ve even made all their data […]
The post Prius isn’t the highestmpg hybrid in 2017! appeared first on SAS Learning Post.
This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
The post PUT it there! Six tips for using PUT and %PUT statements in SAS appeared first on The DO Loop.
]]>This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
For SAS programmers, the PUT statement in the DATA step and the %PUT macro statement are useful statements that enable you to display the values of variables and macro variables, respectively. By default, the output appears in the SAS log. This article shares a few tips that help you to use these statements more effectively.
The PUT statement supports a “named output” syntax that enables you to easily display a variable name and value. The trick is to put an equal sign immediately after the name of a variable: PUT varname=;
For example, the following statement displays the text “z=” followed by the value of z:
data _null_; x = 9.1; y = 6; z = sqrt(x**2 + y**2); put z=; /* display variable and value */ run; 
z=10.9 
You can extend the previous tip to arrays and to sets of variables.
The PUT statement enables you to display elements of an array (or multiple variables) by specifying the array name in parentheses, followed by an equal sign in parentheses, as follows:
data _null_; array x[5]; do k = 1 to dim(x); x[k] = k**2; end; put (x[*]) (=); /* put each element of array */ put (x1 x3 x5) (=); /* put each variable/value */ run; 
x1=1 x2=4 x3=9 x4=16 x5=25 x1=1 x3=9 x5=25 
This syntax is not supported for _TEMPORARY_ arrays. However, as a workaraound, you can use the CATQ function to concatenate array values into a character variable, as follows:
temp = catq('d', ',', of x[*]); /* x can be _TEMPORARY_ array */ put temp=; 
Incidentally, if you ever want to apply a format to the values, the format name goes inside the second set of parentheses, after the equal sign: put (x1 x3 x5) (=6.2);
The previous tip displayed all values on a single line. Sometimes it is useful to display each value on its own line. To do that, put a slash after the equal sign, as follows:
... put (x[*]) (=/); /* put each element on separate lines */ ... 
x1=1 x2=4 x3=9 x4=16 x5=25 
You can display all values of all variables by using the _ALL_ keyword, as follows:
data _null_; x = 9.1; y = 6; z = sqrt(x**2 + y**2); A = "SAS"; B = "Statistics"; put _ALL_; /* display all variables and values */ run; 
x=9.1 y=6 z=10.9 A=SAS B=Statistics _ERROR_=0 _N_=1 
Notice that in addition to the userdefined variables, the _ALL_ keyword also prints the values of two automatic variables named _ERROR_ and _N_.
Just as the PUT statement displays the value of an ordinary variable, you can use the %PUT statement to display the value of a macro variable. If you use the special “&=” syntax, SAS will display the name and value of a macro variable. For example, to display your SAS version, you can display the value of the SYSVLONG automatic system macro variable, as follows:
%put &=SYSVLONG;

SYSVLONG=9.04.01M4P110916
The results above are for my system, which is running SAS 9.4M4. Your SAS version might be different.
You can display the name and value of all userdefined macros by using the _USER_ keyword. You can display the values of all SAS automatic system macros by using the _AUTOMATIC_ keyword.
%let N = 50; %let NumSamples = 1e4; %put _USER_; 
GLOBAL N 50 GLOBAL NUMSAMPLES 1e4
There you have it: six tips to make it easier to display the value of SAS variables and macro variables.
Thanks to Jiangtang Hu who pointed out the %PUT &=var syntax in his blog in 2012.
For additional features of the PUT and %PUT statements, see:
The post PUT it there! Six tips for using PUT and %PUT statements in SAS appeared first on The DO Loop.
This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
The post What to do in Orlando, during SAS Global Forum! appeared first on SAS Learning Post.
]]>This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
They say “a picture is worth 1000 words” – and I think it might be more like 2000 when it comes to planning out fun/interesting things to do in a new city! I’m going to the SAS Global Forum (#SASGF) conference in Orlando this year, and I was wondering where […]
The post What to do in Orlando, during SAS Global Forum! appeared first on SAS Learning Post.
This post was kindly contributed by SAS Learning Post  go there to comment and to read the full post. 
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 
“How do I find all the private user folders for SAS users that have been deleted so I know which folders can be removed?” I was asked this question recently and thought that I should be able to build up a single line XMLSELECT style SAS® metadata query to answer it. I could then paste … Continue reading “Finding Private User Folders for Deleted SAS Platform Users”
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 
Lately I have been looking at audit histories with the SAS® platform. This is to answer the “Who viewed/changed what and when?” type of question. The core support for this is provided by the SAS Logging Facility. Customizing logging for the many and varied SAS platform components across a distributed environment, collecting logs, processing them, … Continue reading “SAS Platform Audit History: Options and Versions”
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 
The post Ten posts from 2016 that deserve a second look appeared first on The DO Loop.
]]>This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
Last week I wrote about the 10 most popular articles from The DO Loop in 2016.
The popular articles tend to be about elementary topics that appeal to a wide range of SAS programmers. Today I present an “editor’s choice” list of technical articles that describe more advanced statistical methods in SAS.
I’ve grouped the articles into three categories: statistical graphics and visualization, statistical computations, and matrix computations. If you are a SAS statistical programmer, these articles deserve a second look.
Ten posts from The DO Loop that deserve a second look #SASTip
Click To Tweet
SAS ODS graphics provides an easy way to create standard graphs for data analysis. The graphs in this list are more sophisticated:
These article show helpful statistical techniques that you should know about:
The SAS DATA step is awesome. For many programming tasks, it is an efficient and effective tool. However, advanced analytical algorithms and multivariate statistics often require matrixvector computations, which means programming in the SAS/IML language.
There you have it, 10 articles from The DO Loop in 2016 that I think are worth a second look. Did I omit your favorite article? Leave a comment.
The post Ten posts from 2016 that deserve a second look appeared first on The DO Loop.
This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
The post ODS OUTPUT: Store any statistic created by any SAS procedure appeared first on The DO Loop.
]]>This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
In the beginning SAS created procedures and output. The output was formless and void. Then SAS said, “Let there be ODS,” and there was ODS.
Customers saw that ODS was good, and SAS separated the computation from the display and management of output.
The preceding paragraph oversimplifies the
SAS Output Delivery System (ODS), but the truth is that ODS is a powerful feature of SAS. You can use ODS to send SAS tables and graphics to various output destinations, including HTML, PDF, RTF, and PowerPoint. You can control the style and attributes of the output, thus creating a customized report. There have been hundreds of papers and books written about ODS. A very basic introduction is Olinger (2000) “ODS for Dummies.”
To a statistical programmer the most useful destination is the OUTPUT destination. The OUTPUT destination sends a table or graph to a SAS data set. Consequently, you can programmatically access each element of the output.
The implications of the previous statement are monumental. I cannot overstate the importance of the OUTPUT destination, so let me say it again:
The ODS OUTPUT destination enables you to store any value that is produced by any SAS procedure. You can then read that value by using a SAS program.
The ODS OUTPUT destination answers a common question that is asked by new programmers on SAS discussion forums: “How can I get a statistic into a data set or into a macro variable?”
The steps are as follows:
New to #SAS programming? How to get any statistic into a data set.
Click To Tweet
As an example, suppose that you intend to use PROC REG to perform a linear regression, and you want to capture the Rsquare value in a SAS data set. The documentation for the procedure lists all ODS tables that the procedure can create, or you can use the ODS TRACE ON statement to display the table names that are produced by PROC REG. The data are the 428 vehicles in the Sashelp.Cars data set, which is distributed with SAS:
ods trace on; /* write ODS table names to log */ proc reg data=Sashelp.Cars plots=none; model Horsepower = EngineSize Weight; quit; ods trace off; /* stop writing to log */ 
Output Added:  Name: FitStatistics Label: Fit Statistics Template: Stat.REG.FitStatistics Path: Reg.MODEL1.Fit.Horsepower.FitStatistics  
By looking at the output, you can see that the third table contains the Rsquare value. By looking at the SAS log, you can see that the name of the third table is “FitStatistics.”
Now that you know the name of the ODS table is “FitStatistics,” use the ODS OUTPUT destination to write that table to a SAS data set, as follows:
ods output FitStatistics=Output; /* the data set name is 'Output' */ proc reg data=Sashelp.Cars plots=none; /* same procedure call */ model Horsepower = EngineSize Weight; quit; proc print data=Output noobs; run; 
The output from PROC PRINT shows the structure of the output data set. Notice that the data set often looks different from the original displayed table. The data set contains nonprinting columns (like Model and Dependent) that do not appear in the displayed table. The data set also contains columns that contain the raw numerical values and the (formatted) character values of the statistics. The columns cValue1 and nValue1 represent the same information, except that the cValue1 is a character column whereas nValue1 is a numerical column. The same applies to the cValue2 and nValue2 columns. The character values might contain formatted or rounded values.
From the previous PROC PRINT output, you can see that the numerical value of the Rsquare statistic is in the first row and is in the nValue2 column. You can therefore read and process that value by using a standard WHERE clause. For example, the following statements use the SYMPUTX subroutine to create a macro variable that contains the value of the Rsquare statistic:
data _null_; set Output; if Label2="RSquare" then call symputx("RSq", nValue2); run; %put RSq = &RSq; 
RSq = 0.6201360929 
The SAS log shows that the Rsquare value is now contained in the Rsq macro variable.
Storing the statistic in a macro variable is only one way to use the data set. You could also read the statistics into PROC IML or PROC SQL for further computation, or show the value of the statistic in a graph.
The previous sections show how to save a single table to a SAS data set. It is just as easy to create a data set that contains multiple statistics, one for each level in a BYgroup analysis.
Suppose that you want to run several regressions, one for each value of the Origin variable, which has the values “Asia,” “Europe,” and “USA.” The following call to PROC SORT sorts the data by the Origin variable.
The sorted data is stored in the CARS data set.
proc sort data=Sashelp.Cars out=Cars; by Origin; run; 
You can then specify Origin on the BY statement in PROC REG to carry out three regression analyses.
When you run a BYgroup analysis, you might not want to see all of the results displayed on the computer screen, especially if your goal is to save the results in an output data set. You can use the ODS EXCLUDE statement to suppress SAS output.
ods exclude all; /* suppress tables to screen */ ods output FitStatistics=Output2; /* 'Output2' contains results for each BY group */ proc reg data=Cars plots=none; by Origin; model Horsepower = EngineSize Weight; quit; ods exclude none; /* no longer suppress tables */ proc print data=Output2 noobs; where Label2="RSquare"; var Origin Label2 nValue2; run; 
The output from PROC PRINT shows the Rsquare statistics for each model. Notice that the BYgroup variables (in this case, Origin) are added to output data sets when you run a BYgroup analysis. You can now use the statistics in programs or graphs.
Some procedures provide an alternative option for creating an output data set that contains statistics. Always check the SAS documentation to see if the procedure provides an option that writes common statistics to an output data set. For example, the documentation for the PROC REG statement states that you can use the OUTEST= option with the RSQUARE option to obtain an output data set that contains the parameter estimates and other model statistics such as the Rsquare value.
Thus for this example, you do not need to use the ODS OUTPUT statement to direct the FitStatistics table to a data set. Instead, you can obtain the statistic as follows:
proc reg data=Cars NOPRINT outest=Output3 RSQUARE; /* statistics in 'Output3' */ by Origin; model Horsepower = EngineSize Weight; quit; proc print data=Output3 noobs; format _RSQ_ 8.6; var Origin _RSQ_; run; 
In summary, the ODS OUTPUT statement enables you to create a data set that contains any statistic that is produced by a SAS procedure. You can use the ODS OUTPUT statement to capture a statistic and use it later in your program.
The post ODS OUTPUT: Store any statistic created by any SAS procedure appeared first on The DO Loop.
This post was kindly contributed by The DO Loop  go there to comment and to read the full post. 
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 
Today, whilst trying to troubleshoot why a SAS Environment Manager Service Architecture configuration was no longer collecting and processing logs, I discovered a handy status option for the emi_init command. I’m posting the help output and status output here to remind me in future Here’s the output from the emi_init help option showing all … Continue reading “SAS Environment Manager Service Architecture: emi_init”
This post was kindly contributed by platformadmin.com  go there to comment and to read the full post. 