Turun ammattikorkeakoulu Ruokahalu kasvaa syödessä lisää makrokielen herkkuja
SAS Makrokieli - kertaus Makrokielen asiat tapahtuvat ohjelmaa käännettäessä makroprosessorin työn tulos näkyy kääntäjälle Idea: yksi nimi korvautuu pitemmällä tekstillä moneen kertaan monessa kohtaa ohjelmaa mahdollisesti vaihtelevasti kyse on aina tekstistä, merkkijonosta Tämä tapahtuu ohjelmaa käännettäessä
Makromuuttujat - kertaus Voidaan määritellä melkein milloin tahansa Sisältää saman arvon kunnes eksplisiittisesti muutetaan muuten sama koko ohjelman (istunnon) ajan Määrittely ja asetus: %let nimi = uusi ; Viittaus: &nimi Havaitaan: &nimi.. Ei: &nimi Kyseinen kohta ohjelmassa korvautuu makron arvolla Makron arvo on aina merkkijono!! SAS-kääntäjä voi ymmärtää sen lukuna
Makro -kertaus Makro on pala koodia, jolle annetaan nimi %macro dsn; data.tiedot %mend dsn; %macro suorita; proc print data = %dsn; run; %mend suorita;
Makro - kertaus Makro on pala koodia, jolle annetaan nimi %macro dsn; data.tiedot %mend dsn; %macro suorita; proc print data = %dsn; run; %mend suorita; Nyt käyttö: title1 Tiedosto %dsn käytössä ; %suorita; Makro voi generoida hyvinkin pitkän pätkän koodia Puolipiste ei ole pakollinen makrokutsun jäljessä.
Filosofista pohdintaa Kun ohjelmassa tarvitaan vakiota, kumpi tapa on parempi: mvakio = 3.14; %let mvakio = 3.14;...... maksu = hinta * mvakio; maksu = hinta * %mvakio; Kumpikin toimii oikein hyvin Mahdollinen ongelma: Jos käytetään valmiita makroja, esiintyykö jossain niistä muuttuja mvakio?
Pieni harjoitus Sitaattien kanssa on joskus epäselvyyttä. Mitkä put-lauseet suoritetaan: %let a = AAA ; %macro puttaa; %put &a; %if &a = AAA %then %put ei sitaatteja; %if &a = AAA %then %put yksinkertaiset; %if AAA = AAA %then %put tasan samat; %if &a = AAA %then %put kaksinkertaiset; %if &a = AAA %then %put kumpaakin; %if &a = AAA %then %put vain toisella puolella; %mend puttaa; %puttaa;
SAS-lokissa näkyy: Pieni harjoitus AAA ei sitaatteja yksinkertaiset tasan samat kaksinkertaiset
%let tiedsto = sasuser.class; %let komment = ; /* eli siis tyhjä */ &komment proc contents DATA = &tiedsto; &komment TITLE Tiedosto &tiedsto ; &komment Tästähän tulee: Kommentoidaanpa osa ohjelmasta proc contents DATA = sasuser.class; TITLE Tiedosto sasuser.class ;
%let tiedsto = sasuser.class; %let komment = ; /* eli siis tyhjä */ &komment proc contents DATA = &tiedsto; TITLE Tiedosto &tiedsto ; &komment Tästähän tulee: Kommentoidaanpa osa ohjelmasta proc contents DATA = sasuser.class; TITLE Tiedosto sasuser.class ; Mutta: %let komment = *; /* asteriski */ Ja tästä tuleekin: * proc contents DATA = sasuser.class; * TITLE Tiedosto sasuser.class ; *
Kommentoidaanpa osa ohjelmasta Toinen tapa: tehdään makro, jota ei kutsuta (käytetä). %macro kommentoi; DATA tiedot; SET havainto; WHERE. PROC TABULATE DATA = tiedot; CLASS. VAR TABLE %mend kommentoi;
Makrokielen funktioista Makrokieli tarjoaa joukon funktioita mielenkiintoinen funtio on %sysfunc voidaan suorittaa jokin SAS-funktio ja saada tulos talteen Esimerkiksi: onko tiedosto olemassa: %macro onkoha( tdsto ); %global onhase; /* varmuuden vuoksi */ %if sysfunc( exist( &tdsto)) %then %let onhase = K; %else %let onhase = E; %mend onkoha: Funktio exist palauttaa 1, jos tiedosto on olemassa, muuten 0 Makromuuttuja onhase saa arvon K tai E vastaavasti.
Makrokielen funktioista Makrokieli tarjoaa joukon funktioita toimivat kuin vastaavannimiset DATAvaiheen funktiot toimivat makrokielen tasolla (siis ennen kääntäjää) käsittelevät merkkijonoja Esimerkiksi: %index %length %scan %qscan %substr %qsubstr ensimmäinen osajonon esiintymä merkkijonossa merkkijonon pituus etsi n:s sana merkkijonosta etsi n:s sana merkkijonosta erota osajono alkaen jostain, pituus jokin sama ohittaen erikoismerkkien merkityksen
Makrokielen funktioista Esimerkki makrossa esiintyy luku väliltä 1-99 saatu jonkin operaation tuloksena nyt tulisi rakentaa siitä nimi muotoa NIMI38 vaan, jospa luvussa onkin vain yksi numero? %if %length( &num ) = 1 %then %let num = 0&num ;.. ja nyt saadaan aikaan myös NIMI01, NIMI02,
Makrokielen funktioista Esimerkki tarkkana pitää olla!! %if %length( num ) = 1 %then %let num = 0&num ;.. ja pieleen menee. %put %length( num ); Tulostaa 3 Miksi?
Makrokielen funktioista Esimerkki kirjoitetaan personoituja kirjeitä Markku on luultavasti Söör Markku. %if %index( &nimi, Markku ) > 0 %then %let nimi = Söör &nimi;
Makrokielen funktioista Esimerkki pomo sai meidät kiinni pelleilystä Söör täytyy poistaa nimen edestä. %if %index( &nimi, Söör ) > 0 %then %do; %let pos = %index( &nimi, Söör ); %let nimi = %qsubstr ( &nimi, &pos+4 ); %end;. %qsubstr ei huomioi erikoismerkkejä, muuten sama kuin %substr &pos+4 on implisiittinen %eval(&pos+4)
Makrokielen funktioista Tehdäänpä analyysi 12:n kuukauden materiaaleista Tätä edeltävä kuukausi ja sitä edeltävät 11 kuukautta Materiaalit nimeltään MAvvvvkk
Esimerkki: juokseva 12 kuukautta %macro anal12mo ; %LET k1 = 01 ; %LET k2 = 02 ; %LET k3 = 03 ; %LET k4 = 04 ; /* Makrokielen vektori */ %LET k5 = 05 ; %LET k6 = 06 ; %LET k7 = 07 ; %LET k8 = 08 ; %LET k9 = 09 ; %LET k10 = 10 ; %LET k11 = 11 ; %LET k12 = 12 ; %LET kk = %sysfunc( month( %sysfunc(today())) ); %LET kk1 = %eval( &kk - 1 ); %LET vuo = %sysfunc( year( %sysfunc( today ()) )); %LET vv1 = %eval( &vuo - 1);
Esimerkki: juokseva 12 kuukautta %macro anal12mo ;... DATA matsku; /* luodaan tyhjä tiedosto */ IF _N_ = 1 THEN STOP; SET MA&vuo&kk1 ( KEEP = );
Esimerkki: juokseva 12 kuukautta %macro anal12mo ;... DATA matsku; /* luodaan tyhjä tiedosto */ IF _N_ = 1 THEN STOP; SET MA&vuo&kk1 ( KEEP = ); %DO i = &kk %TO 12 PROC APPEND BASE = matsku DATA = MA&vv1&&k&i ( KEEP = ) ; %END
Esimerkki: juokseva 12 kuukautta %macro anal12mo ;... DATA matsku; /* luodaan tyhjä tiedosto */ IF _N_ = 1 THEN STOP; SET MA&vv&kk1 ( KEEP = ); %DO i = &kk %TO 12 PROC APPEND BASE = matsku DATA = MA&vv1&&k&i ( KEEP = ) ; %END %DO i = 1 %TO &kk1 PROC APPEND BASE = matsku DATA = MA&vuo&&k&i ; %END /* materiaali koottu, suorita analyysi */ PROC XXXX DATA = matsku ; %mend anal12mo;
%macro anal12mo ; Esimerkki: variaatio äskeisestä DATA matsku; /* luodaan tyhjä tiedosto */ IF _N_ = 1 THEN STOP; SET MA&vuo&kk ( KEEP = ); %DO i = &kk %TO 12 %let kc = %sysfunc( put( &i ), z2. ); PROC APPEND BASE = matsku DATA = MA&vv1&kc ( KEEP = ) ; %END %DO i = 1 %TO &kk1 %let kc = %sysfunc( put( &i ), z2. ); PROC APPEND BASE = matsku DATA = MA&vuo&kc ; %END /* materiaali koottu, suorita analyysi */ %mend anal12mo;
Esimerkki: juokseva 12 kuukautta, toinen tapa %macro anal12mo ; DATA _NULL_; vv = YEAR( TODAY() 1 ); kk = MONTH( TODAY() ); CALL EXECUTE( DATA matsku; ); CALL EXECUTE( SET ); DO I = 1 TO 12 CALL EXECUTE ( MA!! PUT(vv, 4.)!! PUT(kk, z2. )!! ( KEEP = ) ); kk = kk +1; IF kk > 12 THEN DO kk = 1; vv = vv + 1; END; CALL EXECUTE ( ; ); END; CALL EXECUTE( ); /* tähän väliin tulee tuo kehitetty datavaihe */ PROC XXX DATA = matsku;... %mend anal12mo;
Joka alueelta raportti %macro alueet ; PROC SORT DATA = tiedot( KEEP = ) OUT = matsku; BY alue; DATA _NULL_; SET matsku ( KEEP = alue ); BY alue; IF first.alue THEN DO; i+1; nro = left( put( i, Z2. ); CALL SYMPUT( alu!! nro, alue ); CALL SYMPUT( YHT., nro ); END; Syntyy makromuuttujat alu01, ja YHT Huom: YHT-muuttujan arvo muuttuu ja on lopulta suurin alue
Toistetaanpa samaa %macro alueet ;. CALL SYMPUT( yht, nro ); END; %do i= 1 to &yht; PROC MEANS DATA = matsku mean n max min sum; WHERE alue = &&alu&i ; VAR myynti kulut ; TITLE Alueen &&alu&i myynti ja kulut ; %mend alueet; Tuloksena syntyy PROC MEANS kutakin aluetta kohti Etukäteen ei ehkä tiedetä, montako Toimii, jos aluenumerot ovat 1,2,3,4
Muutamia automaattisia makromuuttujia SAS määrittelee joitakin automaattisia makromuuttujia: &sysday &systime &syslast - viikonpäivä, jolloin suoritus alkoi - kellonaika, jolloin suoritus alkoi - viimeksi luodun tiedoston nimi &komment PROC PRINT DATA = &syslast; &komment TITLE Tiedosto &syslast ; &komment &syserr &syscp - paluukoodi PROC tai DATA-vaiheesta - käyttöjärjestelmä, jossa toimitaan
Nopea ja dynaaminen tapa hakea tietoja taulusta Oletetaan, että annetut koodiarvot ovat SAS-tiedostossa koodit. Seuraavassa esimerkissä SAS-koodi eri värein: Mustalla kirjoitettu koodi suoritetaan periaatteessa kerran datavaiheen alussa tai lopussa vihreällä kirjoitettu koodi suoritetaan jokaisella datavaiheen kierroksella punaisella kirjoitettu koodi suoritetaan aika ajoin - siis muutamia kertoja. 13 12/30/99
Nopea ja dynaaminen tapa hakea tietoja taulusta Oletetaan, että annetut koodiarvot ovat SAS-tiedostossa koodit. Esimerkki: %let lib = sasuser; %let fromlib = prod; %let valipit = 800; /* valitaan sopivasti esim. yli 1000 */ PROC SQL; CREATE TABLE %lib.nwxyz LIKE %fromlib.nwxyz; QUIT; 14 12/30/99
PROC SQL; CREATE TABLE %lib.nwxyz LIKE %fromlib.nwxyz; QUIT; DATA nwxyz ( keep = client_r client_0 activity client_1 ); STOP; /* ehkä haluamme tänne vain osan */ SET %lib.nwxyz; /* DB2-taulun muuttujista */ 14 12/30/99
DATA _null_ ; /* Tämä datavaihe kehittää nopean kyselyn */ LENGTH lause $80; RETAIN vali &valipit; SET koodit end = loppu; IF _n_ = 1 THEN DO ; call execute( "PROC SQL ; " ); END; 15 12/30/99
IF vali = &valipit THEN DO; call execute( " INSERT into nwxyz ") ; lause = "( SELECT client_number, client_code,"!! client_type, client_key " ; call execute( lause ); call execute( "FROM &fromlib.nwxyz " ); call execute( "WHERE client_cat = '1' " ) ; call execute( "AND client_type IN (' ','1')" ); call execute( "AND client_number IN ( " ) ; END; 15 12/30/99
DATA _null_ ; LENGTH lause $80;... IF vali = &valipit THEN DO;... END; call execute( client_number ) ; /* tai: ( "'"!! client_number!! "'" ) */ vali + (-1) ; /* vähennetään laskuria */ IF ( vali = 0 ) OR loppu THEN DO; call execute( " ) ) " ) ; /* Lopeta SQL */ vali = &valipit; END; ELSE call execute( "," ); IF loppu THEN call execute( " QUIT; ") ; 16 12/30/99
Nopea dynaaminen tapa hakea tietoja taulusta Tämä on nopea ja dynaaminen tapa hakea tietoja taulusta. Emme tiedä etukäteen, montako koodia tulee hakea Ohjelma näyttää monimutkaiselta, mutta ei loppujen lopuksi ole erityisen hankala. Saavutettu hyöty ylittää moninkertaisesti nähdyn vaivan. 16 12/30/99
Netti tulvii lisätietoja, ohjeita ideoita ja vastauksia. Vaikkapa: support.sas.com/resources/papers/tnote/tnote_base.html sascommunity.org/wiki/user:rolandrb sascommunity.org/wiki/category:macro_language datasavantconsulting.com/roland/sastips.html tdiasug.dartmouth.edu/presentations/20021213_sr_macro.pdf basas.com/tips.html Lisätietoja ja malleja
Yhteenveto Pieni sana, %macro, antaa valtavasti vaihtelua ohjelmaan. Makrojen ja makromuuttujien avulla voi ohjelmista tehdä joustavampia helpompia ylläpitää selkeitä: muuttuvat asiat ohjelman alussa hyvin nähtävillä lyhyempiä paremmin uudelleenkäytettäviä lisäämättä kohtuuttomasti ohjelman tekemisen vaikeutta
This is the end The Doors