EGENDEFINERTE FUNKSJONER I SAS OG LITT OM OPEN SOURCE INTEGRASJON SAS FANS I STAVANGER 21.10.2015, MARIT FISKAAEN (SAS INSTITUTE)
EGENDEFINERTE FUNKSJONER INNLEDNING 2 På FANS 4. mars 2015 ble det vist hvordan man kan bruke PROC FCMP til å lage egendefinerte funksjoner i SAS (fra SAS 9.2) PROC PROTO kan brukes til å skrive funksjoner i C/C++ og til å linke inn DLL-fil med funksjoner (DLL: Dynamic Link Library). Vi viser hvordan man kan kalle egendefinerte funksjoner fra SAS Data Integration Studio (DIS). PROC FCMP kan også brukes til å lage subrutiner (om man ønsker å returnere mer enn en verdi) Litt om open source integrasjon.
3 PROC FCMP INNLEDNING Hva er proc FCMP? FCMP akronym for Function Compiler Lage funksjoner vha data steg syntaks Kalle funksjonene fra data steg akkurat som man gjør med vanlige SAS funksjoner Nestede funksjoner Fordeler: Mer oversiktlig kode Gjenbrukbare funksjoner Enkelt, ligner en del på egendefinerte funksjoner i Visual Basic
PROC FCMP LAGE FUNKSJONER I PROC FCMP 4 Vise bruk av proc fcmp i EG fra forrige FANS presentasjon: proc fcmp outlib=sasuser.fcmp_fun.functions; function my(a, b, logc, x) label='dødsintensitet for en x-åring'; return ( a + b * 10 ** (logc * x)); endsub; run; options cmplib=sasuser.fcmp_fun; data work.dods_intensitet; my_50=my(0, 0.000027, 0.042, 50); run;
EGENDEFINERTE FUNKSJONER I C/C++ PROC PROTO
PROC PROTO BRUKE C KODE I PROTO 6 proc proto package = sasuser.fcmp_fun.functions; double my_proto(double a, double b, double logc, double x); externc my_proto; double my_proto(double a, double b, double logc, double x) { double r; r = a + b * pow(10, (logc * x)); return r; } externcend; run;
PROC PROTO BRUKE C KODE I PROTO 7 proc fcmp inlib=sasuser.fcmp_fun outlib=sasuser.fcmp_fun.functions; function SAS_my_proto(a,b,logc,x); x=my_proto(a, b,logc,x); return(x); endsub; quit; options cmplib=sasuser.fcmp_fun; data work.dodsint_proto; a=sas_my_proto(0, 0.000027, 0.042, 50); run;
EGENDEFINERTE FUNKSJONER FRA DLL-FIL PROC PROTO
9 PROC PROTO DLL INNLEDNING Laget en dll-fil med Microsoft Visual Studio. Hvordan det kan gjøres er beskrevet i vedlegg. Her viser vi kun en veldig enkel funksjon, for å illustrere hvordan dette kan gjøres. Viser så hvordan man kan bruke PROC PROTO for å kalle funksjoner fra DLL-fila.
PROC PROTO DLL STI FOR DLL OG BIBLIOTEK 10 /* Angi sti for dll-filen: */ %let root = c:\users\normfi\documents\visual studio 2013\Projects\FunksjonerLivsforsikring\x64\Release; /* Definer biblioteket der SAS datasettet som inneholder funksjonene som er deklarert vha. proc proto: */ libname lib "&root";
PROC PROTO DLL LINK TIL DLL 11 /* Bruker PROC PROTO til å definere bibliotek og datasett der funksjonene er lagret:*/ proc proto package=lib.proto_livsf label="funklivsforsikring" stdcall; /* Kopler SAS til DLL'en som inneholder de kompilerte C funksjonene: */ link "&root\funksjonerlivsforsikring.dll" ; /* Deklarerer funksjonene: */ double myx(double a, double b, double logc, double x) label="dødsintensitet for en x-åring"; run;
PROC PROTO DLL PROC FCMP 12 /* Bruker FCMP slik at C funksjonskallene kan brukes i datasteg: */ proc fcmp inlib=lib.proto_livsf outlib=lib.proto_livsf.funklivsforsikring; /* Definerer en wrapper funksjon for hver av C funksjonene: */ function sas_myx(a, b, logc, x); x1=myx(a, b, logc, x); return(x1); endsub; quit; /*Fortelle hvor funksjonene som er kompilert er:*/ options cmplib=lib.proto_livsf;
PROC PROTO DLL LAGE DATASETT MED ALDER 13 /*Datasett med alderene vi vil kalle funksjonen vår for:*/ data work.alderdata; input alder; datalines; 0 10 20 30 40 50 60 70 80 90 100 110 run;
PROC PROTO DLL KALLE FUNKSJONEN FRA DATASTEG 14 /*Makrovariabler, R-63 for menn:*/ %let a=0; %let b=0.000027; %let logc=0.042; /*Kaller C-funksjonen fra datasteg:*/ data work.resultat_myx; set work.alderdata; my_dll = sas_myx(&a, &b, &logc, alder); kontroll_my=0 + 0.000027*10**(0.042*alder); run; proc fcmp listfuncs inlib=lib.proto_livsf; run;
PROC PROTO DLL RESULTAT FRA KJØRING 15
EGNE FUNKSJONER I SAS DI STUDIO
EGNE FUNKSJONER FRA SAS DI STUDIO LAGE FUNKSJON I EG 17 Man kan benytte egendefinerte funksjoner i jobber i SAS Data Integration Studio (DIS). Først laget vi funksjon vha. EG: Vi kunne alternativt valg å legge hele koden som lager funksjonene i en jobb på en UWC node i DIS. Se side 26.
EGNE FUNKSJONER FRA SAS DI STUDIO REGISTRERE TABELLEN I SAS DI STUDIO 18 Vi registrerer tabellen ved å høyreklikk på LIB velg «Register Table» (ellers ser vi ikke tabellen i DIS).
EGNE FUNKSJONER FRA SAS DI STUDIO VI LAGER EN JOBB 19 Valgte UWC node: Legger inn flg. kode:
EGNE FUNKSJONER FRA SAS DI STUDIO LEGGER TIL KOLONNER PÅ TARGET TABELL 20 Husk å legge inn target kolonner. Vi vil se x og myx, velg type «Numeric».
EGNE FUNKSJONER FRA SAS DI STUDIO RESULTAT 21 Kjør jobb Stå på tabell og velg «Open»:
EGNE FUNKSJONER FRA SAS DI STUDIO BRUKE FUNKSJON I EXPRESSION 22 Vi lager ny jobb med «Extract» node: Bruker prekode på node:
EGNE FUNKSJONER FRA SAS DI STUDIO BRUKE FUNKSJON I EXPRESSION 23 Vi mapper alder og legger til kolonnen som vi kaller Myx Myx er numerisk og legger på expression Mapper alder til Myx
EGNE FUNKSJONER FRA SAS DI STUDIO RESULTAT 24
EGNE FUNKSJONER FRA SAS DI STUDIO FUNKSJON BASERT PÅ PROC PROTO 25 Helt tilsvarende kan vi kalle funksjonen fra DLL-filen. I EG kode som vist tidligere med proc proto + fcmp. Så på DI-jobben prekode på extract node: options cmplib=lib.proto_livsf; Så bruker vi funksjonen fra dll-fila:
EGNE FUNKSJONER FRA SAS DI STUDIO JOBB SOM DEFINERER FUNKSJONENE 26 Legger til proc fcmp koden som UWC: Må registrere tabellen FUN i biblioteket LIB for å se den i DIS.
EGNE FUNKSJONER FRA SAS DI STUDIO JOBB SOM KALLER FUNKSJONENE 27
EGNE FUNKSJONER FRA SAS DI STUDIO RESULTAT 28
PROC FCMP SUBRUTINER
30 PROC FCMP SUBRUTINER Vi har sett på egendefinerte funksjoner, men man kan også lage subrutiner vha. PROC FCMP. Mens funksjoner returnerer kun en verdi så kan man vha. subrutiner returnere mer enn en verdi.
PROC FCMP SUBRUTINER - EKSEMPEL 31 proc fcmp outlib=sasuser.fcmp_fun.functions; subroutine my_subrutine(a, b, logc, x, my_sub, test) label='dødsintensitet - subrutine'; outargs a, b, logc, x, my_sub, test; my_sub=( a + b * 10 ** (logc * x)); test=x*2; return; endsub; run; options cmplib=sasuser.fcmp_fun; data work.subrutine_dods_intensitet; a=0; b=0.000027; logc=0.042; x=50; my_sub=.; test=.; call my_subrutine(a, b, logc, x, my_sub, test); run;
PROC FCMP SUBRUTINER - EKSEMPEL 32 Resultat:
OPEN SOURCE INTEGRASJON PROC IML KALLE R
34 PROC IML INNLEDNING SAS Interactive Matrix Language (IML) er en SAS prosedyre, PROC IML. IML er et matrise språk som har innebygd operatorer og funksjoner for de fleste standard matrise operasjoner (f.eks. matrise multiplikasjon, transponering, determinant, invers). Vi vil her se på et enkelt eksempel på multiplikasjon av en vektor med en matrise. Man kan kalle R fra PROC IML.
PROC IML KODE 35 proc iml; *kaller IML; b = {1 2 3}; *1 x 3 vektor; c = {1.0 0 0, 0.2 1.0 0, 0.8 0.4 1.0}; *3 x 3 matrise; d=b*c; *matrise multiplikasjon; print d; *skriver resultat av multiplikasjon; quit; *lukker IML;
PROC IML RESULTAT 36 Resultat EG: Uten IML måtte lage løkke for å multiplisere og summere riktige element:
PROC IML MELDING OM IKKE IML TILGJENGELIG 37
38 PROC IML KALLE R Artikkelen http://wuss.org/proceedings14/85_final_paper_pdf.pdf viser bla. at vi kan kalle R fra proc iml (s. 6): PROC IML; SUBMIT / R; x <- c(1:3) print(x) ENDSUBMIT; QUIT;
PROC IML KALLE R 39 C:\Program Files\SASHome\SASFoundation\9.4
PROC IML KALLE R 40 Grunnen til feilmeldingen var at R ikke var installert på imaget. Nå virker det:
41 PROC IML SJEKKE OM SAS IML ER INSTALLERT / LISENSIERT Sjekke hva som er installert: PROC PRODUCT_STATUS; RUN; Udokumentert prosedyre som forteller hva som er lisensiert: PROC SETINIT; RUN;
OPEN SOURCE INTEGRASJON BASE SAS JAVA OBJECT
OPEN SOURCE INTEGRASJON LINK TIL ARTIKKEL OG FILER 43 Artikkel: https://communities.sas.com /docs/doc-10746 Her finner vi link til filer som kan brukes og her er en pdf som beskriver detaljene SAS_Base_OpenSrcIntegrat ion.pdf
OPEN SOURCE INTEGRASJON FORUTSETNINGER FOR Å FÅ KJØRT DETTE EKSEMPELET 44 Viktig med riktig java versjon. Jeg brukte JDK (Java development kit) 1.7.0. update 15. Installerte Anaconda Python 2.7 og R-3.2.1. Hadde problem med å installere kernlab, men fikk installert den fra Rstudio vha kommandoen install.packages( kernlab ).
OPEN SOURCE INTEGRASJON EKSEMPEL FRA ARTIKKEL 45 Bruker Base SAS Java Object Man har her et R og et Python script Kaller R og Python kode fra sas datasteg. Resultatet av kjøringen av scriptene legges i csv-filer. Resultatene fra csv-filene leses inn til SAS vha PROC IMPORT Bruke disse nye sas datasettene som vanlig i SAS proc er
OPPSUMMERING HOVEDPUNKT
47 OPPSUMMERING HOVEDPUNKT Har man formler som skal programmeres kan det være hensiktsmessig å benytte PROC FCMP. Vi har sett at egendefinerte funksjoner kan brukes på flg. måter: Lage formler direkte i PROC FCMP Bruke C++ kode i PROC PROTO Linke inn DLL-fil i PROC PROTO Jobber man mye med matriser kan SAS IML være nyttig. Vi kan kalle R fra SAS IML. Man kan kalle f.eks. Python og R vha. Base SAS Java Object
VEDLEGG LAGE DLL-FIL
49 VEDLEGG LAGE DLL-FIL 1) Lastet ned Microsoft Visual Studio, gratis fra https://www.visualstudio.com/products/visual-studio-community-vs 2) Åpne Visual Studio og lag et prosjekt: File + New Project Velg: «Win 32 Console Application» og finn et navn (her «FunksjonerLivsforsikring») Velg «DLL» under application settings + Finish. Visual studio solution: C:\Users\normfi\Documents\Visual Studio 2013\Projects\FunksjonerLivsforsikring\ FunksjonerLivsforsikring.sln
50 VEDLEGG LAGE DLL-FIL - FORTS (1) 3. Skriv inn kode. // FunksjonerLivsforsikring.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <iostream> extern "C" _declspec(dllexport) double _cdecl myx(double a, double b, double logc, double x); //Funksjon for dødsintensiteten til en x-åring double myx(double a, double b, double logc, double x) { double r; r = a + b * pow(10, (logc * x)); return r; }
51 VEDLEGG LAGE DLL-FIL - FORTS (2)
52 VEDLEGG LAGE DLL-FIL - FORTS (3) 4) Velg riktig konfigurasjon. Hvis bruker 64-bit SAS må bruke 64-bit dll.
53 VEDLEGG LAGE DLL-FIL FORTS (4) 5) Bygg DLL-fil. «BUILD» + «Build FunksjonerLivsforsikring» I output-vinduet finner man navnet på DLL-filen: c:\users\normfi\documents\visual studio 2013\Projects\FunksjonerLivsforsikring\x64\Release\FunksjonerLivsforsikring.dll Man kan åpne filen i notepad og søke om man finner myx (den skal være der). Husk å lagre prosjektet. Man kan bruke «Rebuild» for å bygge filen på ny. Tilbake