Wsparcie Techniczne
Programowanie w SAS
Najczęstsze problemy i pytania związane z programowaniem w SAS
Dowiedz się więcej na temat programowania w SAS oraz samej pracy w różnych środowiskach programowania.
Gdzie szukać przykładowych kodów SAS?
Przykładowe kody SAS można znaleźć na tej stronie.
Polecamy także materiały z SAS Global Forum oraz stronę SAS Blogs.
Czy w systemie SAS można zdefiniować własną funkcję?
Tak, służy to tego procedura PROC FCMP dostępna od wersji SAS 9.2. Można także użyć narzędzia FCmp Function Editor, które jest dostępne w menu SAS (Rozwiązania → Analiza).
Przykład
proc fcmp outlib=work.funkcje.test;
function inverse(in);
if in=0 then inv=.;
else inv=1/in;
return(inv);
endsub;
run;
options cmplib=work.funkcje;
data test;
do i=0 to 2;
x=inverse(i);
output;
end;
run;
Czy można zdefiniować format za pomocą funkcji?
Jest to nowa funkcjonalność, wprowadzona w wersji 9.3.
Przykład:
proc fcmp outlib=work.funkcje.test;
function zamien(c $) $;
return( scan(c,2)||' '||scan(c,1) );
endsub;
run;
options cmplib=(work.funkcje);
proc format;
value $ imie_nazwisko (default=100) other=[zamien()];
run;
data _null_;
osoba='Kowalski Jan';
format osoba $imie_nazwisko.;
put osoba;
run;
Jak najłatwiej określić ostatni dzień bieżącego miesiąca?
W SAS istnieje wygodna funkcja INTNX służąca do tego typu operacji na datach.
Ostatni dzień bieżącego miesiąca
intnx('month', today(), 0,'end')
Ten sam dzień następnego roku
intnx('year', today(), 1,'same')
Więcej informacji i przykładów: INTNX Function.
Z jaką precyzją SAS przechowuje liczby?
Upraszczając, na zachowanie precyzji przy przechowywaniu liczb w SAS-ie można liczyć przy liczbach o długości do 15 znaków.
Uściślając:
- maksymalna liczba całkowita możliwa do przechowania jest zwracana przez funkcję constant('EXACTINT',8).
- trzeba pamiętać, że liczby z częścią ułamkową zamieniane na reprezentację binarną (komputerową) mogą stracić na precyzji.
Ilustruje to poniższy kod:
data _null_;
v=12345678901234567;
put v= @18 v 17.;
v=999999999999999; *15 cyfr;
put v= @18 v 17.;
v=9999999999999999; *16 cyfr;
put v= @18 v 17.;
v=0.1234567890123456;
put v= @18 v 17.16;
v=123456.7890123456;
put v= @17 v 18.10;
v=0.999999999999999; *15 cyfr po przecinku (kropce);
put v= @18 v 17.16;
v=0.9999999999999999; *16 cyfr po przecinku (kropce);
put v= @18 v 17.16;
x=15.7-11.9;
if x=3.8 then
put 'równe';
else
put 'wyliczone ' x= 'nie jest równe 3.8';
x=0;
do i=1 to 10;
x+0.1;
end;
if x=1 then
put 'równe';
else
put 'wyliczone ' x= 'nie jest równe 1';
run;
Warto też wspomnieć, że zagadnienie jest bardziej związane z przechowywaniem liczb dziesiętnych w formacie zmiennoprzecinkowym w pamięci komputera, niż z samym SAS-em.
Co oznacza komunikat NOTE: The query requires remerging summary statistics back with the original data?
Gdy w PROC SQL, we frazie SELECT jest więcej zmiennych bez funkcji agregujących niż we frazie GROUP BY, SAS w odróżnieniu od innych baz danych pokaże komunikat: NOTE: The query requires remerging summary statistics back with the original data a agregacja nie zostanie wykonana - zwrócone zostaną dane szczegółowe. Jest to opisane w dokumentacji, jak również w nocie SN-4308.
W wersji SAS 9.2 dostępna jest opcja NOSQLREMERGE, której ustawienie spowoduje, że w sytuacji "remerging" pojawi się błąd i przetwarzanie zostanie przerwane.
Jak grupować po wartościach wyliczanych w procedurze SQL?
Pisząc zapytania w SQL często konieczne jest wyliczenie i pogrupowanie danych według nowej wartości.
Czy jest to możliwe do wykonania w jednym kroku, a jeżeli tak, to jak to zrobić?
- Pierwszym podejściem jest na ogół umieszczenie formuły wyliczającej nową wartość w klauzuli SELECT i powtórzenie jej w klauzuli GROUP BY, np.
SELECT oddzial || '-' || departament as oddzial1, sum(wartość)
FROM dane.zbior
GROUP BY oddzial || '-' || departament;Po uruchomieniu takiego kodu wynik nie jest taki, jaki był oczekiwany, a w logu pojawia się komunikat NOTE: The query requires remerging summary statistics back with the original data.
Oznacza on, że grupowanie nie mogło zostać przeprowadzone poprawnie. Dzieje się tak dlatego, że dla SASa wyrażenie w SELECT i GROUP BY to dwa różne wyrażenia, co oznacza, że użytkownik chciał grupować dane według zmiennej, której nie ma w SELECT. A takie grupowanie nie jest poprawne.
- Wystarczy jednak drobna modyfikacja kodu, żeby uzyskać spodziewany wynik:
SELECT oddzial || '-' || departament as oddzial1, sum(wartość)
FROM dane.zbior
GROUP BY CALCULATED oddzial1;
W tym przypadku grupy zostaną wyznaczone poprawnie, dane będą zagregowane, a w logu nie będzie żadnego ostrzeżenia.
Jak wczytać dane z arkusza Excel, jeśli kolumna zawiera dane mieszanych typów?
Polecamy notę: SN-006123.
Jak przekierować wynik działania procedury do zbioru SAS?
Niektóre procedury mają wbudowany mechanizm zapisu wyników do zbioru. Mechanizmem uniwersalnym, dla wszystkich procedur jest ODS output. Jeżeli wynik działania procedury zawiera kilka sekcji to wcześniej należy uruchomić komendę ODS trace on. Spowoduje ona wypisanie w logu wszystkich sekcji 'outputu'.
Przykład:
ods trace on;
ods output summary=tabelka;
proc means data=sashelp.class;
run;
Wynik działania procedury MEANS (sekcja summary) zostanie zapisany w zbiorze tabelka.
Jakiego formatu użyć aby wyświetlić liczbę z przecinkiem jako separatorem dziesiętnym?
Poniższy data step demonstruje użycie kilku formatów:
data _null_;
l=-3384.70;
- domyślny format;
put l; - bez spacji między tysiącami;
put l numx12.2; - ze spacją między tysiącami przy locale=Polish;
put l nlnum12.2; - z kropką między tysiącami;
put l commax12.2; - długość formatu jest przykładowa;
run;
Jak w SAS Base sprwadzić dni świąteczne w danym roku?
W SAS 9.4 pojawił się zestaw funkcji SAS będących jednym z elementów ułatwiających uwzględnianie dat i okresów specjalnych w obliczeniach czy analizach czasowych (podobnych do tych, które wykorzystywane były w module SAS/ETS). Zestaw wspomnianych elementów, zwierający funkcje HOLIDAY, a także procedury DATEKEYS oraz opcję EVENTDS=, jest obecnie dostępny w Base SAS. Wspomniane mechanizmy pozwalają na definiowanie dat oraz interwałów czasowych, które są związane ze specjalnymi wydarzeniami - takimi jak święta narodowe czy okresy sprzedaży.
Opis mechanizmów znajduje się w dokumencie dostępnym pod tym linkiem.
Uwaga: zarówno dokument (status 'Preproduction' - wersja robocza) jak i procedura DATEKEYS jest na etapie weryfikacji i testowania, a niektóre z opisywanych procedur czy funkcji są nowe, więc możliwe są przyszłe zmiany w ich działaniu, w tym ich rozszerzanie i uzupełnianie uwzględniające lokalną - również polską - specyfikę (na przykład tworzenie reguł typu 'Święto Niepodległości przypada na 11 listopada'); dlatego wartościowe będą dla nas wszelkie uwagi dotyczące działania obecnej wersji, oraz pomysły na ich rozszerzanie.
Jak można nakładać formaty na makrozmienne?
Należy użyć funkcji putn, funkcja put nie może być użyta w wywołaniach %SYSFUNC ani %QSYSFUNC.
Przykład wyświetlenia systemowej makrozmiennej &sysdate w formacie yymmdd10. :
%put %sysfunc(putn("&sysdate"d,yymmdd10.));
Jak odczytać makrozmienną zawierającą znak & bez dalszego jej rozwijania?
Umożliwia to funkcja %superq. Jako argument przyjmuje nazwę makrozmiennej bez znaku "&"
Przykład:
%let m=1;
data _null_;
mz='m&m';
call symput ('mz',mz);
run;
%put &mz;
%put %superq(mz);
Jak najłatwiej policzyć słowa w (makro)zmiennej?
Za pomocą funcji countw.
Może być ona pomocna w makro programowaniu, na przykład przy konstrukcji pętli:
%let zmienne=
m1
m2
m3
;
%put liczba słów=%sysfunc(countw(&zmienne));
%macro m;
%do i=1 %to %sysfunc(countw(&zmienne));
%put %scan(&zmienne,&i);
%end;
%mend;
%m;
Jaka jest maksymalna długość makrozmiennej?
Wartość ta zależy od platformy sprzętowej, zwykle jest to 65534 bajtów.
Jak sprawdzić w makrze, czy zbiór istnieje?
Zmienna exist będzie ustawiona na 1 jeśli zbiór istnieje lub na zero jeśli nie.
%let exist=%sysfunc(exist(nazwa_zbioru));
Komunikat WARNING: Apparent symbolic reference not resolved.
W makroprogramie wyliczam makrozmienną. Niestety dostaję komunikat WARNING: Apparent symbolic reference not resolved.
Najprawdopodobniej makrozmienna w programie nie została zadeklarowana jako makrozmienna globalna. Domyślnie wszystkie makrozmienne tworzone w ramach makroprogramu są lokalne.
Przykład działającego programu:
%macro lobs(dset);
%global L_OBS;
proc sql noprint;
select count(*) into :L_OBS from &dset;
quit;
%mend;
%lobs(sashelp.air);
%put &L_OBS
Jak usunąć globalne makrozmienne zdefiniowane przez użytkownika?
Można do tego użyć makro funkcji %SYMDEL w następujący sposób
%SYMDEL makrozmienna(e);
Aby usunąć wszystkie globalne makrozmienne użytkownika można użyć kodu:
%macro delvars; data vars;
set sashelp.vmacro;
run;
data _null_;
set vars;
if scope='GLOBAL' then
call execute('%symdel '||trim(left(name))||';');
run;
%mend;
%delvars
W jaki sposób użyć makrozmiennej SYSDATE?
Przykład:
options yearcutoff = 1920 ;
data _null_ ;
date = input("&sysdate",date7.) ;
put date ddmmyy10. ;
run ;
Jak można definiować kolory w SAS/GRAPH?
W SAS można używać nazw opisowych i następujących modeli przestrzeni barw: RGB, RGBA, CMYK, HLS, HSV oraz skali odcieni szarości.
Sposoby te są opisane w Color-Naming Schemes.
Dostępny jest również zestaw makr ułatwiających pracę z kolorami i umożliwiających konwersję pomiędzy modelami: Using the Color Utility Macros.
Jak usprawnić tworzenie grafiki w SAS?
Tym, którym tworzenie zaawansowanych wykresów w systemie SAS wydaje się trudne lub skomplikowane polecamy:
- Tworzyć grafikę interaktywnie w Enterprise Guide (np. za pomogą kreatorów).
- Skorzystanie z gotowych wzorców zawierających liczne przykładowe rysunki i wykresy wraz z kodami.
Dostępne są one na tej stronie.
Ogólne informacje o ODS Graphics Designer.
Nowe narzędzie do edycji i tworzenia wykresów.
Dostępne wraz z modułem SAS/GRAPH. Uruchomienie poprzez wywołanie makra %sgdesign
ODS Graphics Designer jest dostępny począwszy od wersji SAS 9.2 Etap 2 (TS2M0).
Szczegóły w nocie 37185.
Jak zainstalować SAS/GRAPH control for ActiveX?
Raporty w HTMLu zawierające obiekty ActiveX wymagają zainstalowania ActiveX na komputerze użytkownika, który tę stronę będzie oglądał. Jak to zrobić? Jak to wygląda licencyjnie?
Licencyjnie nie ma żadnych ograniczeń. Kontrolka może być instalowana u dowolnej liczy użytkowników.
Najnowszą wersję programu instalacyjnego można ściągnąć z naszych stron zewnętrznych → SAS/GRAPH Software.
Udostępniając użytkownikom strony html zawierające obiekty ActiveX, mamy 2 możliwości:
- Zainstalować kontrolkę ręcznie, kopiując na lokalny komputer program instalacyjny
- Program instalacyjny może być uruchamiany automatycznie, kiedy użytkownik po raz pierwszy wyświetla stronę z grafiką w tym formacie.
W tym przypadku program instalacyjny musi być umieszczony na serwerze www, a w instrukcji ODS tworzącej stronę HTML musi być użyta opcja ARCHIVE= wskazująca na miejsce, gdzie umieszczony został program instalacyjny, np. ODS HTML File = 'c:\temp\sastest.html' Archive = "http://www.server.com/sasweb/graph/sasgraph.exe";
Przy okazji warto wspomnieć, że aplikacja Web Report Studio nie wspiera grafiki wygenerowanej w formacie ActiveX. Grafika generowana w tym formacie jest automatycznie zamieniana na ACTXIMG (podobnie, kiedy wykorzystywany jest driver JAVA, jest on automatycznie zamieniany na JAVAIMG). Dzieje się tak, żeby WRS mogło pozostać w pełni aplikacją, która nie wymaga instalowania na lokalnym komputerze żadnego oprogramowania.
Jak sprawdzić jaki format ODS jest aktualnie aktywny?
Wraz z SAS 9.2, można programowo sprawdzić jaki format wyników ODS jest aktualnie aktywny. Można to zrobić przez wykonanie zapytania na tabeli słownikowej DICTIONARY.DESTINATIONS. W wyniku zapytania otrzymujemy informację o aktywnym formacie ODS oraz o aktualnie przypisanym stylu. Podobnie jak dla innych tabeli słownikowych, te same informacje znajdują się w widoku SASHELP.VDEST.
Jak kontrolować rozmiar strony w ODS dla formatu RTF i PDF?
Rozmiar strony jest kontrolowany poprzez opcję: OPTIONS PAPERSIZE=LETTER;
Wartość tej opcji jest uzależniona od sterownika drukarki. Przykładowe wartości to LETTER, LEGAL, A4. Możliwe jest także ustawienie własnego formatu papieru poprzez: options papersize=("4.5" "7"); Takie użycie powoduje ustawienie formatu papieru 4,5 cala na 7 cali.
Jak dodać tekst pomiędzy wynikami w pliku HTML ODS?
Należy użyć wyrażenia ODS TEXT='text-string', np.:
options center nodate nonumber;
ods html file='c:\temp\info.html' style=sasweb;
proc print data=sashelp.class(obs=5);
title 'Informacje z PROC PRINT';
footnote 'Stopka procedury PRINT';
var name age height weight;
run;
ods html text='
To jest tekst dopisany bezpośrednio za procedurą PRINT.
';
proc freq data=sashelp.shoes;
title 'Informacje z PROC FREQ';
footnote 'Stopka proc FREQ';
tables region;
run;
ods html text='
Tekst po wynikach PROC FREQ.
';
ods html close;
Jak zmienić tytuł w ramce nawigatora dokumentu HTML?
Możemy użyć opcji title = w instrukcji ODS HTML.
Przykład:
Możemy użyć opcji title = w instrukcji ODS HTML.
Jak włączyć własne logo do tworzonego pliku HTML?
Procedura TEMPLATE pozwala na definiowanie stylów, które można zastosować do własnych dokumentów HTML. Zobaczmy przykład stylu styles.test opartego na stylu DEFAULT, to znaczy zachowujemy całą definicję tego stylu dodając tylko obrazek po prawej stronie na górze dokumentu.
proc template;
define style styles.test;
parent=styles.default;
style body from document /
prehtml="<table width=100%> <td align="right">
<img src=""c:\images\img1.jpg""> </table>";
end;
run;
Stylu tego używamy w następujący sposób:
ods html file='c:\temp\ods.html' style=styles.test;
/* Nasz kod SAS */
ods html close ;
Jak w ODS HTML użyć styli stworzonych za pomocą Enterprise Guide?
Enterprise Guide tworzy pliki CSS (Cascade Style Sheet) które można wykorzystać w instrukcji ODS HTML.
Przykład instrukcji :
ODS HTML file='c:\temp\test.html'
stylesheet=(
url="c:\Enterprise Guide\Styles\test.css");
proc print data=sashelp.class;
run;
ODS HTML CLOSE;
Jak zmienić tytuł w Output?
Domyślnie przy wykonywaniu poleceń na górze strony drukowany jest tytuł "The SAS System". Tytuł można zmienić instrukcją TITLE:
TITLE Nowy Tytuł;
Jeśli nie chcemy żadnego tytułu wykonujemy instrukcję:
TITLE;
Gdzie mogę znaleźć więcej informacji dotyczących ODS?
Radzimy zapoznać się z następującą stroną www.
Jak uzyskać więcej informacji w okienku LOG?
W tym celu można ustawić w SAS dodatkowe opcje. Oto najczęściej używane:
- Base SAS
DETAILS, ERRORS, MSGLEVEL, NOTES, SOURCE, SOURCE2, ECHOAUTO - makra
MLOGIC, MPRINT, SYMBOLGEN, MERROR, SERROR - wydajność
FULLSTIMER - SAS/Access
Informacje w nocie SN-000207. - SAS/Connect
1. odkomentować pierwsze wiersze w pliku tcp*.scr (trace on; echo on;)
2. ustawić opcje
-set TCPDEBUG N /* N = 0..63 */
-set TCPDFILE 'sciezka do pliku z logiem tcp' - inne
DATASTMTCHK, DKRICOND, DKROCOND, DLDMGACTION, DSNFERR
MERGENOBY,
DATE, NEWS, OVP, PRINTMSGLIST
UNBUFLOG
Niektóre opcje zależą od systemu operacyjnego. Informacje na ich temat można uzyskać w dokumentacji SAS
Jak zapisywać log w trakcie przetwarzania, bez potrzeby czekania na koniec zadania?
Domyślnie informacje, które będą zapisywane w logu, są buforowane i wypisywane dopiero po zapełnieniu bufora lub zakończeniu zadania. Na takie zachowanie ma wpływ opcja LOGPARM, ustawiana przy starcie SASa, a konkretnie jej parametr WRITE, który domyślnie ma wartość BUFFERED:
LOGPARM="WRITE=BUFFERED | IMMEDIATE"
Jeżeli istnieje potrzeba śledzenia logu na bieżąco, należy ustawić:
LOGPARM="WRITE=IMMEDIATE"
Przy takim ustawieniu informacje do loga będą wypisywane natychmiast
Jak debugować działanie data-stepu?
Należy dodać opcję "/debug", jak w przykładzie poniżej:
data zbior / debug;
...
run;
Jak debugować działanie SAS/Access do relacyjnych baz danych?
Należy ustawić poniższe opcje, które spowodują zapisanie w logu SASowym szczegółowych informacji na temat poleceń wysyłanych do silnika bazy danych. Szczegóły w dokumentacji "Online Doc".
options sastrace=',,d,d' sastraceloc=saslog;
Jak interpretować błędy w logu?
Jeżeli komunikat o błędzie jest niezrozumiały zalecamy przeszukanie not sasowych (SAS Notes) pod kątem występowania danego komunikatu.
W tym celu należy wejść na stronę wsparcia technicznego.
Lub z Menu głównego SAS-a wybrać: Pomoc → SAS na Webie → Wsparcie Techniczne
Następnie można skorzystać z okienka 'Search' w górnej części ekranu. Należy wpisać treść błędu dopisując ewentualnie dodatkowe informacje, takie jak wersję SAS-a czy wersję systemu operacyjnego.
Uwaga: Jeżeli komunikat z błędem jest po polsku należy uruchomić SAS-a w wersji angielskiej i przeszukiwać noty z komunikatem w wersji angielskiej.
Jak programowo sprawdzić czy dany produkt jest licencjonowany?
Należy użyć funkcji sysprod('nazwa produktu'). Funkcja zwraca 1 jeśli licencja dla danego produktu jest ważna, 0 jeśli jest nieważna, -1 jeśli nazwa produktu jest nierozpoznana. Funkcji można użyć w datastep-ie, SCL lub w IML step-ie, np.:
data _null_;
licensed=sysprod('pc file formats');
put licensed=;
licensed=sysprod('base');
put licensed=;
licensed=sysprod('abc');
put licensed=;
run;
W jaki sposób odczytać wartość zmiennej środowiskowej?
Do odczytania wartości zmiennej środowiskowej służy m.in. funkcja sysget() i makro funkcja %sysget().
Przykład:
data _null_;
x=sysget('TMP');
put x;
run;
%let OS_NAME=%sysget(OS);
%put &OS_NAME;
Jak powiązać nazwę katalogu zawierającego bibliotekę WORK z identyfikatorem sesji SAS?
Nazwa katalogu ze zbiorami roboczymi zawiera w sobie numer sesji (PID).
- Przykład dla Windows:
Dla sesji SAS o numerze PID 2212 powstaje katalog _TD2212 - Przykład dla UNIX:
Dla sesji SAS o numerze 9730 powstaje katalog SAS_work2E6E00002602_sun1. W tym przypadku 2602 to zapisana szesnastkowo dziesiętna liczba 9730.
Jak ograniczyć zajętość biblioteki WORK podczas sortowania dużych tabel?
W tym celu należy użyć opcji TAGSORT (jest to opcja procedury SORT). Dzięki niej, w plikach roboczych zapisywane są jedynie pola kluczowe a nie całe rekordy. Opcja ta może dać bardzo dużą poprawę wydajności jeżeli sortujemy zbiór o dużej liczbie zmiennych a sortowanie odbywa się według jednej lub kilku zmiennych.
Co zrobić, aby okno poleceń zamykało się automatycznie po wykonaniu polecenia X?
Należy ustawić opcję: options NOXWAIT.
Czy SAS musi czekać na zakończenie wykonywania polecenia X?
SAS czeka na zakończenie wykonywania polecenia X, ponieważ domyślnie ustawiona jest opcja XSYNC.
Aby to zmienić należy ustawić opcję: options NOXSYNC.
Jak otworzyć zbiór zawierający kolumny z nałożonymi formatami, których nie posiadamy?
Przed otwarciem należy ustawić opcję options nofmterr;
Czy konieczne jest uruchamianie PC File Server, aby wykorzystywać SAS/ACCESS to PC File Formats na UNIXach?
SAS/Access to PC File Formats na UNIXach daje możliwość exportu lub importu plików do Excela za pomocą procedury export/import, np.
proc export dbms=xlsx outfile='/home/sasdemo/myexcel.xlsx'
data=sashelp.class replace;
run;
proc import dbms=xlsx datafile='/home/sasdemo/myexcel.xlsx'
out=class replace;
sheet='myexcel';
run;
Począwszy od SAS 9.1.3 Service Pack 3 nie ma potrzeby uruchamiania PC File Servera (na PC).
Możliwość eksportu do konkretnego arkusza dostępna jest w wersji SAS 9.2, natomiast w 9.1.3 po zainstalowaniu hot fixa E9PF06.
Ile procesów jest startowanych po uruchomieniu SAS-a poleceniem sas na Unixie?
Startowane są 2 lub 3 procesy. Dla sesji batchowej są to sas i elssrv, dla sesji interaktywnej: sas, elssrv i motifxsassm.
Rolę procesu (m.in.) elssrv opisuje nota: SN-015231.