LISTSERV at the University of Georgia
Menubar Imagemap
Home Browse Manage Request Manuals Register
Previous messageNext messagePrevious in topicNext in topicPrevious by same authorNext by same authorPrevious page (July 2012, week 2)Back to main SAS-L pageJoin or leave SAS-L (or change settings)ReplyPost a new messageSearchProportional fontNon-proportional font
Date:         Sun, 8 Jul 2012 22:52:22 -0600
Reply-To:     Fried Egg <friedegg2012@GMAIL.COM>
Sender:       "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From:         Fried Egg <friedegg2012@GMAIL.COM>
Subject:      Re: Understanding environment where run_macro executes
In-Reply-To:  <201207082356.q688xlQa005345@waikiki.cc.uga.edu>
Content-Type: text/plain; charset=ISO-8859-1

I spent less than 30 minutes on this, but it works for your example. The basic concept is to build a R script file and execute it in batch mode in R. The SAS7BDAT package for R doesn't work on my machine so I just use xpt files in both directions. If no additional processing on the data being retrieved from R is necessary then the set statement is unnecessary and the datastep would just need to be a null. I think it would be interesting to build a client side adapter to Rserve for SAS Foundation. Overall I still think there is little point to reinventing the wheel when it already exists with SAS/IML.

%macro xportsds; libname xpt xport "%sysfunc(dequote(&path))"; proc copy in=%sysfunc(dequote(&libref)) out=xpt; select %sysfunc(dequote(&sds)); run; libname xpt clear; %mend;

%macro xportxpt; libname xpt xport "%sysfunc(dequote(&xpt))"; proc copy in=xpt out=%sysfunc(dequote(&olib)) memtype=data; run; libname xpt clear; %mend;

%macro rxeq; filename rpgm temp; data _null_; file rpgm lrecl=32767; put "%sysfunc(dequote(&rpgm))"; run; x /usr/lib64/R/bin/R CMD BATCH %sysfunc(pathname(rpgm,f)); filename rpgm clear; %mend;

proc fcmp outlib=work.func.rndm; subroutine xportsds(sds $,libref $,path $); rc=run_macro('xportsds',sds,libref,path); endsub;

subroutine xportxpt(xpt $,olib $); rc=run_macro('xportxpt',xpt,olib); endsub;

subroutine rxeq(rpgm $); rc=run_macro('rxeq',rpgm); endsub; run;

options cmplib=work.func;

data linreg2; call xportsds('class','sashelp','/home/sas/class.xpt'); call rxeq(compbl(

'library(SASxport); library(Zelig); library(sqldf);

cls <- read.xport(''/home/sas/class.xpt''); z.o1 <- zelig( AGE ~ SEX + WEIGHT + HEIGHT , model = ''aov'' , data = cls ); resid <- z.o1$residuals; fit <- z.o1$fitted.values; residual <- cbind( cls , resid , fit ); cof <- data.frame( SexC = z.o1$coefficients[2] , WeightC = z.o1$coefficients[3] , HeightC = z.o1$coefficients[4] ); linreg <- sqldf(''select l.* , r.SexC , r.WeightC , r.HeightC from residual as l , cof as r''); write.xport(linreg,file=''/home/sas/linreg.xpt'',autogen.formats=FALSE);'

));

call xportxpt('/home/sas/linreg.xpt','work');

do _n_=1 by 1 until(done); set class(obs=1) linreg open=defer; if _n_>1 then do; *do something else; output; end; end;

stop; run;

On Sun, Jul 8, 2012 at 5:56 PM, Roger DeAngelis <rogerjdeangelis@gmail.com>wrote:

> Hi Toby, > > That was a bogus posting in so many ways. I realized it after I sent it > but I did't know how to delete it. You are correct about symget in the same > dataset. Thanks for correcting me. Typically a macro variable with the > average would only be available after the last observation was processed. > Here it is right after the set on observation 1. I am a little rusty since > I > have been away for a couple of years. It was supposed to be a proof of > concept but even the concept was wrong. There are many better ways to get > the deviation with other SAS functionality. > > Here is the problem I have been working on, which brings together some of > the recent posts. This is a proof of concept and I know about R and IML, > proc reg and sums of squares and deviations from procedures like proc corr. > I know it would look cleaner in pure SAS. But R has over 3,000 packages. > > /* the following R code performs > proc reg data=sashelp.class coef=cof?; > model Age = Sex Weight Height; > output out=linreg residual=resid predicted=fit; > run > > Without SAS STA and inside base SAS datastep. > > The dataset returned from R has the following structure. > sashelp.class plus regression output > > # Variable Type Len Label > > 1 RESID Num 8 Residual from Regression > 2 FIT Num 8 Fitted Value > 3 SEXC Num 8 Coefficient of Sex > 4 WEIGHTC Num 8 Coefficient of Weight > 5 HEIGHTC Num 8 Coefficient of Height > 6 NAME Char 8 > 7 SEX Char 1 > 8 AGE Num 8 > 9 HEIGHT Num 8 > 10 WEIGHT Num 8 > > If there is interest in the code I will > gladly send it to anyone who is interested. > It is to much to paste into this message. > > I hope others will find R as useful as I have > > */ > > data linreg (drop=pgm); > > length pgm $1024 resid fit sexc weightc heightc 8.; > > label > Resid ="Residual from Regression" > Fit ="Fitted Value" > SexC ="Coefficient of Sex" > WeightC ="Coefficient of Weight" > HeightC ="Coefficient of Height"; > > set class(obs=1) r.linreg open=defer; > > if _n_=1 then do; > /* R CODE */ > pgm=compbl(" > > library(sas7bdat); # read sas7bdat; > library(SASxport); # create xport dataset; > library(Zelig); # proc reg; > library(sqldf); # proc sql; > > cls <- read.sas7bdat('c:\\utl\\class.sas7bdat'); > # proc reg; > z.o1 <- zelig(Age ~ Sex + Weight + Height, > model = ""aov"", data = cls); > resid <- z.o1$residuals; > fit <- z.o1$fitted.values; > residual <- cbind(cls,resid,fit); > cof <- data.frame(SexC=z.o1$coefficients[2], > WeightC=z.o1$coefficients[3],HeightC=z.o1$coefficients[4]); > > # sql to join with coeficients; > linreg <- sqldf('select l.*, r.SexC, r.WeightC, > r.HeightC from residual as l, cof as r'); > write.xport(linreg,file='C:\\utl\\linreg.xpt',autogen.formats=FALSE); > "); > /* EXECUTE R CODE */ > call rxeq(pgm); > end; > else output; > > run; >


Back to: Top of message | Previous page | Main SAS-L page