SAS je registrovaná ochranná známka SAS Institute, Inc., Cary, NC, USA
(c) 2000 Michal Kulich, 1998 Oliver Schabenberger
1. Vytváření datových souborů SASu
2. Manipulace s datovými soubory SASu
3. Programování v datových procedurách SASu
Datové soubory SASu se vytvářejí pomocí datových procedur začínajících klíčovým slovem DATA. Každý datový soubor se skládá z pozorování a veličin. Můžeme si je představit jako matici, kde sloupcům odpovídají veličiny a řádkům pozorování. Každá veličina (tj. sloupec matice) má své jméno nejvýše osm znaků dlouhé. Pokud uživatel nestanoví jinak, datové soubory SASu se ukládají do dočasného pracovního direktoráře, který se po ukončení práce se SASem maže. V kapitole 1.6 je vysvětleno, jak vytvářet trvalé datové soubory a uschovávat je do vlastních direktorářů.
Veličina 1 | Veličina 2 | Veličina 3 | |
Pozorování 1 ----> | |||
Pozorování 2 ----> | |||
Pozorování 3 ----> |
Data, která se mají uschovat v datovém souboru, mohou být přímou součástí SASového programu. V takovém případě ručně vypisujeme jednotlivé hodnoty z klávesnice v PROGRAM EDITORu anebo zkopírujeme hodnoty z jiného textového souboru, například pomocí kláves Ctrl-C a Ctrl-V. Následující datová procedura ukazuje, jak vytvořit datový soubor pojmenovaný ANKETA, který má deset pozorování a sedm veličin zvaných ID, POHL, VEK, PRIJEM, R1, R2, R3. Data mohou představovat výsledky ankety mezi zákazníky, kde PRIJ značí měsíční příjem v tisících a R1 až R3 jsou ohodnocení oblíbenosti tří určitých výrobků.
Příkaz DATA ANKETA znamená, že se bude vytvářet datový soubor jménem ANKETA. Příkaz INPUT definuje jména veličin pro datový soubor ANKETA a tím určuje i jejich počet. Znak $ za jménem veličiny POHL (všimněte si, že je oddělený mezerou) indikuje, že tato veličina je znaková, tj. obsahuje znakové řetězce a ne čísla. Příkaz DATALINES signalizuje ukončení příkazů datové procedury--následující příkaz již obsahuje konkrétní hodnoty dat oddělené mezerami, vždy jedno pozorování na každém řádku. Všimněte si, že řádky dat nejsou oddělené středníky. Všechna vstupní data se považují za jeden příkaz a středník (nepovinný) následuje až za poslední načítanou hodnotou posledního pozorování. Příkaz DATALINES má ekvivalentní formu CARDS, již lze používat zcela zámenně. Příkaz CARDS se uchoval z dob, kdy se data načítala z děrných štítků (angl. punchcards) a protože evokoval prastarý původ SASu jako děrnoštítkového programu, byl úředně přejmenován na DATALINES (i když z celého SASu ty děrné štítky ještě pořád vyloženě čiší - pozn. překl.).
Právě provedená datová procedura nevydává žádný výstup až na záznam v LOG okně, potvrzující, že v pořádku proběhla. Chceme-li si data prohlédnout, napíšeme PROC PRINT; RUN; a dostaneme výstup v OUTPUT window:
Znakové (řetězcové) veličiny, jako například POHL, je třeba vždy identifikovat v příkazu INPUT znakem $ za jejich jménem. Opomenutí tohoto znaku by mělo za následek načtení chybějícího pozorování namísto každé znakové hodnoty v domněle numerické proměnné. Data ANKETA by pak vypadala takto:
a tak dále.
Někdy je nutné sdělit SASu něco víc o umístění jednotlivých načítaných hodnot na řádce. Taková potřeba například nastane, načítáme-li řetězcovou veličinu, jejíž hodnoty nemají stejnou délku anebo obsahují uvnitř mezery.
Příkaz INPUT definuje veličiny JMENO, VEK, MESTO a STAT. Specifikace $1-25 za názvem veličiny JMENO znamená, že JMENO je znaková veličina, jejíž hodnoty jsou uloženy ve sloupcích 1 až 25 každé datové řádky. Znaková veličina MESTO se načítá ze sloupců 34 až 48. VEK je numerická veličina, jejíž hodnoty jsou umístěny kdekoli mezi hodnotami pro JMENO a MESTO, tj. nekde ve sloupcích 26-33. STAT je znaková veličina a její hodnoty se mohou nalézat kdekoli od sloupce 49 dále.
Kdybychom specifikaci $34-48 pro veličinu MESTO nahradili pouhým označením $ pro znakovou veličinu, data by se načetla následovně:
Jelikož mezera v datovém řádku odděluje hodnoty jednotlivých veličin, SAS nalezne nejprve řetězec 'Hrochův' a přiřadí ho veličině MESTO. 'Týnec' pak musí být hodnota pro veličinu STAT. Zbytek řádku se ignoruje, protože již pro něj nezbývají žádné veličiny.
Datové řádky mohou obsahovat více hodnot, než kolik je potřeba pro jedno pozorování. Přebývající hodnoty se normálně ignorují (viz předchozí odstavec). Pokud ale příkaz INPUT končí specifikací @@, jednotlivé hodnoty se načítají a přiřazují veličinám sekvenčně, bez ohledu na datové řádky. Například následující dvě datové procedury vytvářejí tentýž datový soubor. První:
a druhá:
Bez specifikace @@ by druhá procedura vytvořila pouhá dvě pozorování z prvních tří hodnot na každém řádku.
Načítání dat přímo z ASCII souborů je výhodnější než vypisování hodnot přímo do SASového programu, zvláště u velkých souborů. K načtení ASCII souboru slouží příkaz INFILE předcházející příkaz INPUT uvnitř datové procedury. Struktura a význam příkazu INPUT se přitom nemění, příkaz DATALINES nebo CARDS není třeba uvádět. Struktura načítaného ASCII souboru je úplně stejná, jako by byl jeho obsah uveden přímo v datové proceduře po příkazu DATALINES.
Příkaz INFILE specifikuje ASCII soubor, který se má načíst. Je možné ho použít dvěma způsoby. Buď přímo uvést jméno i s celou cestou, např.
nebo nejprve přiřadit souboru nějakou vnitřní SASovou přezdívku (fileref) příkazem FILENAME a tu pak používat místo celého jména, např.
Jestliže hodnoty v ASCII souboru nejsou odděleny mezerami, ale jinými oddělovacími znaky, můžeme použít parametr DELIMITER příkazu INFILE. Podobným způsobem můžeme vynechat některá pozorování ze začátku ASCII souboru a určit, kolik pozorování celkem chceme načíst (parametry FIRSTOBS a OBS). Například
načte 100 pozorování z ASCII souboru c:\mujdir\data\soubor.txt počínaje pozorováním č. 12 a předpokládá, že jednotlivé hodnoty jsou odděleny čárkami namísto mezerami (což platí například pro *.prn soubory z Excelu).
Ačkoli dBase již nepatří mezi nejpoužívanější databázová prostředí, její datový formát se stále používá a mnohé softwarové balíky jsou schopny číst a psát data ve formátu dBase. Datový soubor dBase lze snadno předělat na SASový datový soubor pomocí procedury DBF. Stačí napsat
a výsledkem je SASový datový soubor dbdata. Parametr DB4 procedury DBF uvádí přezdívku (fileref) databázového souboru, který má být ve formátu dBaseIV. Pro formát dBaseIII+ použijte místo toho DB3, pro formát dBaseV použijte DB5.
SAS automaticky ukládá všechny vytvořené datové soubory do dočasného pracovního direktoráře, který po skončení práce maže. Tento direktorář bývá umístěn někde pod \sas\saswork\ a datové soubory SASu se v něm uschovávají pod jménem, s jakým byly vytvořeny, s koncovkou .sd2. Chceme-li uschovávat své datové soubory pro další práci, abychom je nemuseli znovu vytvářet při příštím spuštění SASu, musíme je uschovat v jiném direktoráři, který si sami zvolíme.
SAS nazývá direktoráře knihovnami. Chceme-li pracovat s konkrétním direktorářem, v SASu jej definujeme jako novou knihovnu, jíž přiřadíme její vnitřní jméno. K jednotlivým souborům se pak v SASu přistupuje dvousložkovým jménem, kde první složka určuje knihovnu (direktorář) a druhá složka jméno vlastního souboru. Tak například dočasný pracovní direktorář má v SASu jméno WORK a všechny soubory v něm uložené se jmenují WORK.SOUBOR. Vytvoříme-li data XYZ procedurou
SAS bude nazývat vytvořený soubor WORK.XYZ. Ke všem souborům v knihovně WORK je ovšem možné také přistupovat bez uvedení jména knihovny, takže my můžeme ve svých programech uvádět buď DATA=xyz nebo DATA=work.xyz.
Potřebujeme-li pracovat s jiným direktorářem, ukládat do něj permanentní soubory a znovu je načítat, musíme tomuto direktoráři přiřadit vnitřní SASové jméno příkazem LIBNAME. Tomuto vnitřnímu jménu se v SASu říká libref a není to vlastně nic jiného než odkaz na direktorář:
Chceme-li nyní vytvořit datový soubor a uschovat ho v direktoráři c:\vyzkum\data\brouci (neboli v knihovně BROUKDIR), napíšeme:
Tento soubor můžeme dále libovolně používat pod jménem broukdir.br1. Jeho jméno na disku jest c:\vyzkum\data\brouci\br1.sd2.
Tabulky Excelu mohou být načteny do SASu několika různými způsoby, z nichž uvádíme dva.
Z hlavního menu zvolíme
. Objeví se okno, kde si zvolíme formát dat, která se mají zkonvertovat (např. Excel 5.0) a postupně doplníme potřebnou informaci. Konverse proběhne nejsnáze, jestliže má excelovská tabulka podobnou stavbu jako SASový soubor (veličiny, pozorování) a obsahuje v prvním řádku jména proměnných, pokud možno vyhovující konvencím SASu (max. osm znaků, bez mezer, začíná písmenem). SAS je schopen předělat jména veličin, které jeho konvencím nevyhovují. Po ukončení konverse je třeba zkontrolovat výsledná data (PROC PRINT).Pozor: Ačkoli nabídka Import obsahuje volbu pro Excel 7.0 (Excel97), tabulky zapsané v tomto formátu nebudou správně zkonvertovány. Pro import do SASu je třeba tabulky ukládat ve formátu Excel 5.0 (Excel 95) nebo Excel 4.0.
Tato metoda konverse je nejvšestrannější a nejméně průhledná. Vyžaduje nainstalovaný modul SAS/ACCESS. Pokud se po spuštění
objeví okno, je tento modul k disposici. Před použitím modulu ACCESS musíme zvolit pracovní direktorář pro soubory potřebné ke konversi a přiřadit mu libref.
Konversní program používající PROC ACCESS můžeme napsat třeba takto:
Tento program načte excelovskou tabulku c:\mujdir\excel\data\soyref95.xls a zkonvertuje ji v SASový datový soubor SOYBEAN. Data se berou z listu REF95. Argumenty GETNAMES, ASSIGN a UNIQUE specifikují, že jména veličin se mají brát z prvního řádku tabulky a upravit, aby byla jednoznačná. Nakonec se mažou pracovní soubory pomocí procedury DATASETS.
Datový soubor můžeme v SASu smazat pomocí PROC DATASETS. Vymažme nyní dva soubory SOUB1 a SOUB2 z dočasného pracovního direktoráře (knihovna WORK):
Chceme-li vymazat všechny soubory v daném direktoráři, napíšeme
kde MOJEDIR je dříve definovaný libref daného direktoráře (třeba LIBNAME mojedir c:\vyzkum\data\stara';).
Chceme-li vědět, jaké veličiny obsahuje daný datový soubor, zdali jsou numerické nebo znakové a jak jsou formátovány, spustíme proceduru CONTENTS. Použití je prosté:
Pokud potřebujeme názvy veličin uchovat k pozdějšímu zpracování, zapíšeme výstup z procedury CONTENTS do datového souboru.
Argument NOPRINT zabrání textovému výstupu na obrazovku při provedení procedury CONTENTS. Výsledky jsou zapsány v datovém souboru VELICINY, bohužel v poněkud nepřehledném stavu.
Manipulace s daty a úpravy datových souborů můžeme provádět v okamžiku vytváření datového souboru (viz kapitola 1) anebo později již jednou vytvořený soubor modifikovat. Obojí se provádí v rámci datové procedury DATA.
Předpokládejme nyní, že máme existující datový soubor MOJEDATA, který chceme upravit. Program vypadá takto:
Příkaz SET mojedata znamená, že SAS má načíst datový soubor MOJEDATA. Poté provede úpravy podle zadaných příkazů a výsledek je uschován zase pod jménem MOJEDATA (jméno vytvářeného souboru jest dáno úvodním příkazem DATA mojedata). Původní obsah souboru MOJEDATA je tedy přepsán, ale pouze pokud celá procedura DATA proběhne úspěšně. Pokud dojde k běhové či syntaktické chybě, původní soubor zůstává nezměněn.
Jestliže chceme uschovat modifikovaný soubor pod jiným jménem, napíšeme
Výsledek je uložen v nově vytvořeném souboru NOVADATA. Zase platí, že v případě chyby se žádný soubor nevytvoří.
Důležitá vysvětlující poznámka k fungování datových procedur:Vnitřek datové procedury, tj. všechny příkazy, které definují a upravují hodnoty jednotlivých veličin, ve skutečnosti funguje jako jeden velký zamlčený for-cyklus, který běží přes všechna pozorování a pro každé z nich postupně provádí jednotlivé příkazy v daném pořadí. V okamžiku, kdy je jedna smyčka for-cyklu u konce, vyplivne se jedno pozorování do vytvářeného souboru. Proto záleží na pořadí jednotlivých příkazů v datové proceduře.
SAS má vestavěnou řadu matematických funkcí, které můžeme použít k jednoduchým transformacím numerických veličin. Seznam funkcí je uveden v nápovědě, přístup k němu je však poměrně komplikovaný. Je třeba postupně zvolit ANKETA (10 pozorování, veličiny ID, POHL, VEK, PRIJEM, R1, R2, R3):
. Zde je příklad s použitím datového souboruVýsledný soubor, taktéž zvaný ANKETA, má 10 pozorování a 17 veličin: 7 původních ID-R3 a 10 nově přidaných. Veličina COSZ se sice vytvoří, ale obsahuje samé chybějící hodnoty. To se stalo proto, že COSZ je transformací veličiny Z, ale ta se počítá až nakonec. Proto v okamžiku výpočtu cos(z) hodnota z ještě není definována.
Nejdůležtější aritmetické, logické a řetězcové operátory jsou uvedeny v následující tabulce ve skupinách podle priority. Operátory s vyšší prioritou se vykonávají dříve než operátory s nižší prioritou. Operátory patřící do téže skupiny se vykovávají zleva doprava.
Skupina | Typ operátoru | Operátor | Popis | Příklad |
0 | () | závorky | y = 3*(x+1); | |
1 | Aritmetický | ** | mocnění | y = x**2; |
2 | Aritmetický | +,- | unární plus, minus | y = -x; |
3 | Aritmetický | * | násobení | y = x * z; |
4 | Aritmetický | +
- |
sčítání
odčítání |
y = x + 3;
z = y - 3*x; |
5 | Řetězcový | || | spojování řetězců | jmeno = krestni || prijmeni; |
6 | Množinový | in | logická konstanta:
je hodnota prvem možiny? |
y = x in (1,2,3,4);
gender in ('F','M'); |
7 | Logický | =, eq | rovná se | if x = 12; |
Logický | <>, ne | není rovno | if x ne 5; | |
Logický | >, gt | je větší | if sin(x) > 0.4; | |
Logický | <, lt | je menší | if cos(x) < sin(z); | |
Logický | >=, ge | větší nebo rovno | ||
Logický | <=, le | menší nebo rovno | ||
8 | Logický | and | logická konjunkce | if (a=b) and (sin(x)>0.3); |
Logický | or | logická alternativa | if (a=b) or (sin(x) < 0.3); | |
Logický | not | negace | if not (a=b); |
Logické výrazy v SASu vracejí hodnotu 1 pro pravdivý výrok, 0 pro nepravdivý. Toho lze využívat například pro kategorisaci spojitých veličin. Jako příklad ukážeme, jak vytvořit ze spojité veličiny VEK věkové skupiny označené 1, 2, 3.
Pozorování s věkem do 25 let mají VEKSK=1, nad 25 let ale do 40 let mají VEKSK=2, nad 40 let VEKSK=3. Stejného výsledku lze docílit pomocí IF...THEN...ELSE:
Přejmenovávání veličin v SASu není složité, ale nese s sebou nečekaný háček, na který je třeba dávat pozor. Jsou dva různé způsoby přejmenovávání veličin a v obou hraje roli klíčové slovo RENAME. To můžeme použít buď jako samostatný příkaz uvnitř datové procedury anebo jako argument pro příkaz SET. První způsob vypadá takto:
A teď RENAME= jako argument:
V obou případech musíme uvést seznam přejmenovávaných veličin ve tvaru <staré jméno>=<nové jméno>. Rozdíl mezi oběma způsoby spočívá v tom, že RENAME jako příkaz provede přejmenování až po úspěšném ukončení celé datové procedury, zatímco RENAME= jako argument přejmenovává veličiny už v okamžiku, kdy jsou kopírovány z původního datového souboru. To znamená, že pokud chceme uvnitř datové procedury s přejmenovávanými veličinami pracovat, musíme používat jejich stará jména, pokud používáme RENAME jako příkaz a jejich nová jména, pokud používáme RENAME= jako argument. Jako ilustraci uvádíme dva příklady:
DATA druha;
SET prvni; RENAME xstare=xnove ystare=ynove; logx=log(xstare); logy=log(ystare); RUN; |
DATA druha;
SET prvni(RENAME=(xstare=xnove ystare=ynove)); logx=log(xnove); logy=log(ynove); RUN; |
Veličiny, kterých se chceme zbavit, můžeme smazat z datového souboru buď pomocí příkazu DROP anebo argumentu DROP příkazu SET. První možnost vypadá takto:
Zde je příklad na druhou možnost:
V obou případech smažeme veličiny R1, R2 a R3. Bývalo by bylo možné ušetřit si psaní a místo r1 r2 r3 napsat r1-r3 se stejným výsledkem.
Jemný rozdíl mezi těmito dvěma způsoby se ukáže, chceme-li mazané veličiny nejprve použít k výpočtům. Například pokud nás nezajímá R1, R2 a R3, ale pouze součet R1+R2+R3, musíme použít
Zde se totiž mazání provede až nakonec, když už jsou výpočty hotové. Druhý způsob, tj.
nefunguje, neboť veličiny R1, R2 a R3 se smažou (resp. vůbec nenačtou) a R obsahuje jen chybějící hodnoty, protože součet nelze spočítat.
Pokud chceme mazat většinu veličin a ponechat jen pár, vyplatí se vyjmenovat pouze ty, které mají zůstat. Pak můžeme použít KEEP namísto DROP. Syntaxe a význam se nemění. Příklady:
anebo
Pokud chceme zpracovávat pouze určitou podmnožinu všech pozorování definovanou pomocí dané logické podmínky, můžeme vytvořit nový zmenšený datový soubor obsahující žádanou podmnožinu a ten pak dále zpracovávat, nebo používat původní soubor a stanovit, která pozorování se mají zpracovat. Druhá alternativa využívá argument WHERE=podmínka, který můžeme přidat ke jménu souboru (do závorek) kdekoliv je to třeba. Například, chceme-li vypsat ze souboru ANKETA všechna pozorování, která mají věk nad 35 let, dáme
Podobně postupujeme při volání jakýchkoli jiných procedur.
Chceme-li raději vytvořit nový datový soubor, napíšeme dovnitř datové procedury, která pozorování se mají ponechat, resp. smazat. Například
Podmínka IF stanovuje, která pozorování se mají ponechat. Místo toho můžeme popsat, která pozorování se mají vymazat. To by vypadalo takto:
Do třetice můžeme použít i argument WHERE:
Vertikální spojování (setting) znamená v podstatě přidávání nových pozorování k původnímu souboru. Mějme dva datové soubory, jeden s n1 pozorováními a množinou veličin V1, druhý s n2 pozorováními a množinou veličin V2. Spojíme-li tyto soubory vertikálně, vznikne datový soubor o n1+n2 pozorováních, který bude mít za množinu veličin sjednocení V1 a V2. Veličiny, které jsou definovány pouze v jednom z datových souborů budou mít chybějící hodnoty pro všechna pozorování pocházející z druhého datového souboru.
Vertikální spojování se provádí několika různými způsoby. První způsob spočívá v uvedení výčtu jmen spojovaných souborů (i více než dva) v příkazu SET datové procedury. Spojený soubor pak můžeme uložit pod libovolným jménem. Jako příklad nyní spojme vertikálně dva datové soubory. Jeden má 15 pozorování a veličiny BLOK, OSETR, RUST, ROK. Druhý má 10 pozorování a veličiny BLOK, OSETR, RUST a SUM. Spojený soubor tedy bude mít 25 pozorování a 5 veličin.
Zde je vypsáno prvních 6 pozorování souboru HRACH1:
Vytvořme druhý soubor HRACH2:
Vypišme na ukázku jen první tři pozorování:
Nyní spojíme HRACH1 a HRACH2 vertikálně:
Druhá metoda vertikálního spojování souborů používá proceduru APPEND
a třetí příkaz APPEND procedury DATASETS
Spojený soubor je v obou příkladech uložen pod jménem ZAKLAD. V případě, že veličiny v obou souborech nejsou totožné (což zahrnuje i znakové veličiny se stejným jménem ale různou délkou), musíme přidat argument FORCE jak do PROC APPEND tak do příkazu APPEND v PROC DATASETS:
Při horizontálním spojování (merging) jde o přidávání nových veličin k původnímu souboru.
Horizontální spojování se používá, máme-li potřebné veličiny rozděleny v několika souborech s (v podstatě) totožnými pozorováními. Provádí se příkazem MERGE uvnitř datové procedury. V nejjednodušším případě dvou souborů s n pozorováními a množinami veličin V1 a V2 je výsledkem horizontálního spojení soubor s n pozorováními a veličinami V1 sjednoceno s V2. Zde je příklad s daty ANKETA: Předpokládejme, že základní informace o účastnících ankety (ID, POHL, VEK, PRIJEM) jsou uschovány v datovém souboru ZAKL a údaje o preferencích jednotlivých výrobků (R1, R2, R3) v souboru PREF. Máme tedy
Nyní tyto dva soubory spojíme horizontálně (vedle sebe):
Výsledkem je soubor ANKETA:
Kdyby soubory ZAKL a PREF obsahovaly aspoň jednu společnou proměnnou, její hodnoty ve výsledném souboru ANKETA by byly vzaty ze souboru PREF, protože ten byl v seznamu souborů příkazu MERGE poslední. Obecně tedy záleží na pořadí specifikace souborů v příkazu MERGE. Kdyby měl soubor ZAKL n1 pozorování a soubor PREF n2<n1 pozorování, vyplnilo by se posledních n1-n2 pozorování ve veličinách R1-R3 chybějícími hodnotami.
Složitější příklady horizontálního spojování datových souborů jsou uvedeny v kapitole 2.10.2 Příkaz BY při spojování setříděných souborů.
Třídění dat obecně znamená seřazení pozorování podle hodnot určité veličiny (veličin). Ale pozor! Pro SAS jsou setříděná data něčím víc než seřazenými pozorováními: Můžeme mít data seřazená v určitém pořadí už od samého počátku, kdy z nich teprve vytváříme SASový soubor, ale pro SAS stejně nebudou setříděná, dokud je neproženeme třídící procedurou. Za chvíli vysvětlíme proč. Setříděná data se v SASu používají, kdykoli potřebujeme provést nějakou proceduru po skupinách podle hodnot určité veličiny. SAS toto umožňuje velmi snadno použitím příkazu BY.
Třídící procedura v SASu se nazývá PROC SORT. Její základní syntaxe je jednoduchá:
Jméno souboru, který se má třídit, je uvedeno v argumentu DATA=. Příkaz BY uvádí seznam veličin, podle kterých se mají data třídit, oddělený mezerami. Nejprve se třídí podle hodnot první veličiny, uvnitř každé její hodnoty se třídí podle druhé veličiny, atd. Z definice se třídění provádí vzestupně podle všech veličin. Chceme-li třídit podle některé veličiny sestupně, připíšeme před její jméno v seznamu BY klíčové slovo DESCENDING. Setříděným souborem se přepíše původní datový soubor. Pokud chceme setříděný soubor raději uschovat pod jiným jménem, musíme si o to říci specifikací argumentu OUT= pro proceduru SORT: PROC SORT DATA=soubor OUT=utrid; Výsledek pak bude uložen jako datový soubor UTRID.
PROC SORT nejenom mění pořadí pozorování v datech, ale přidává do souboru nové skryté veličiny. Jsou-li například data setříděna procedurou SORT podle veličiny TRIDA, vytvoří se navíc veličiny FIRST.TRIDA a LAST.TRIDA s hodnotami 0 a 1, jež udávají jedničkou, které pozorování je první resp. poslední ve své skupině (definované hodnotami veličiny TRIDA). Tyto veličiny normálně nelze zobrazit, ale SAS s nimi počítá a uživatel k nim má přístup alespoň uvnitř datové procedury obsahující příkaz BY trida. Toto je důvod, proč je třeba procedurou SORT třídit i soubory, které jsou naprosto uspořádané.
Příklady třídění: datový soubor HRACH
Nyní setřídíme data podle ošetření a podle bloku:
Zde je prvních 15 pozorování setříděného souboru včetně normálně neviditelných veličin FIRST.OSETR, LAST.OSETR, FIRST.BLOK a LAST.BLOK, které se musejí zobrazovat trikově:
Veličiny FIRST.BLOK a LAST.BLOK obsahují samé jedničky, protože kombinace úrovní veličin OSETR a BLOK obsahují jediné pozorování, které je je zároveň první i poslední.
Chceme-li setřídit hodnoty BLOK sestupně uvnitř každé úrovně veličiny OSETR, napíšeme
Potřebujeme-li setříděná data uložit do jiného souboru, abychom si nepřepsali HRACH, použijeme
Nyní si ještě ukážeme, jak použít skryté veličiny FIRST.OSETR a LAST.OSETR v datové proceduře. Naším úkolem bude vypsat první pozorování z každé úrovně veličiny OSETR:
Výsledkem je soubor s pěti pozorováními:
Příkaz BY lze použít v jakékoli vlastní PROCeduře nebo datové proceduře DATA. Jeho význam v datové proceduře je diskutován ve 2.10.2. Ve vlastní PROCeduře má BY vždycky stejný efekt: procedura se provede zvlášť pro každou kombinaci úrovní veličin uvedených v příkazu BY. Je to stejné, jako bychom předem rozdělili datový soubor na několik podskupin a pak postupně spouštěli proceduru na každé podskupině. Podmínkou použití příkazu BY je předchozí setřídění datového souboru procedurou SORT.
Příkaz BY může být umístěn kdekoli uvnitř procedury a má syntaxi
Seznam veličin, jejichž úrovně se mají kombinovat je oddělen mezerami. Datový soubor musí být předtím setříděn procedurou SORT. Seznam veličin uvedených v příkazu BY musí zahrnovat prvních několik veličin, podle kterých byl soubor setříděn, a to ve stejném pořadí, nikoli však nutně všechny. Například jestliže třídící procedura třídila podle veličin X, Y, Z, U (tj. proběhlo PROC SORT DATA=zkus; BY x y z u; RUN;) , můžeme použít následující příkazy BY:
ale nikoli třeba
Zde je příklad použití příkazu BY: Procedura MEANS počítá popisné statistiky zadané veličiny, např. průměr, či směrodatnou odchylku. Potřebujeme-li spočítat tyto statistiky pro veličinu RUST v datovem souboru HRACH, napíšeme
Chceme-li ale tyto statistiky zvlášť pro každé ošetření, setřídíme nejprve soubor HRACH podle veličiny OSETR a pak spustíme
Příkaz BY má důležitou úlohu při horizontálním spojování datových souborů. Pokud totiž chceme takto spojit dva soubory, které si navzájem neodpovídají uspořádáním jednotlivých pozorování nebo jejich počtem, musíme jednotlivá pozorování identifikovat pomocí jedné nebo několika veličin vyskytujících se v obou souborech (tzv. propojovací veličiny) a pak je správně sestavit. K tomu slouží kombinace příkazů BY a MERGE uvnitř datové procedury, kde v příkazu BY vypíšeme seznam všech propojovacích veličin. Jako vždy při použití příkazu BY musí být oba soubory uspořádány podle všech veličin, které se v příkazu BY vyskytují.
Nejjednodušší situace je spojování dvou souborů, které mají nejvýše jedno pozorování na každou kombinaci propojovacích veličin. Uvažujme následující příklad: V zemědělské studii sledujeme dvě úrovně hnojení fosforem, 0 a 25 liber na akr (veličina P), a tři úrovně vzdálenosti mezi řádky, 40, 80 a 120 cm (veličina VZD). Na každou kombinaci úrovní P a VZD máme 3 políčka identifikovana čísly 1-3 (veličina POLE). Políčka byla osázena a sklizena v roce 1996 a 1997 a bylo zaznamenáno množství sklizené plodiny v obou letech (veličiny UROD96 a UROD97). Ale data jsou ve dvou souborech, zvlášť pro rok 1996 a zvlášť pro rok 1997 a ne všechna políčka byla osázena v obou letech. Nás by zajímal rozdíl v úrodě mezi oběma roky. Proto musíme nejprve oba soubory spojit do jednoho a všechna pozorování přitom správně navázat. Zde jsou data pro oba roky:
DATA pole96;
INPUT p vzd pole urod96; DATALINES; 0 40 1 57 0 40 2 58 0 80 1 57 0 80 2 58 0 80 3 56 0 120 1 49 0 120 2 54 0 120 3 53 25 40 1 53 25 40 2 45 25 40 3 46 25 80 1 54 25 80 2 50 25 80 3 48 25 120 1 63 25 120 2 57 25 120 3 53 ; RUN; |
DATA pole97;
INPUT p vzd pole urod97; DATALINES; 0 40 1 35 0 40 2 28 0 40 3 29 0 80 1 38 0 80 2 29 0 80 3 27 0 120 1 10 0 120 2 25 0 120 3 34 25 40 1 24 25 40 2 24 25 40 3 17 25 80 1 25 25 80 2 31 25 80 3 29 25 120 1 44 25 120 3 28 ; RUN; |
Jednotlivá pozorování jsou jednoznačně charakterisována kombinací úrovní veličin P, VZD a POLE: to jsou propojovací veličiny. Ale všimněme si, že v souboru POLE96 chybí pole č. 3 při P=0 a VZD=40 a v souboru POLE97 chybí pole č. 2 při P=25 a VZD=120. Pokud tyto soubory spojíme takto:
propojí se pozorování z obou souborů přesně v tom pořadí, v jakém jsou uvedena v obou souborech a hodnoty veličin P, VZD a POLE se vezmou ze souboru POLE97. Výsledek bude naprosto chybný. My musíme místo toho propojit pozorování, která mají stejnou kombinaci úrovní P, VZD a POLE. Proto nejprve obě data setřídíme:
a nyní použijeme MERGE s příkazem BY:
Porovnejme nyní, jak vypadají ony spojené soubory:
Nesprávný:
PROC PRINT DATA=polesp1; RUN;
OBS P VZD POLE UROD96 UROD97
1 0 40 1 57 35 2 0 40 2 58 28 3 0 40 3 57 29 4 0 80 1 58 38 5 0 80 2 56 29 6 0 80 3 49 27 7 0 120 1 54 10 8 0 120 2 53 25 9 0 120 3 53 34 10 25 40 1 45 24 11 25 40 2 46 24 12 25 40 3 54 17 13 25 80 1 50 25 14 25 80 2 48 31 15 25 80 3 63 29 16 25 120 1 57 44 17 25 120 3 53 28 |
Správný:
PROC PRINT DATA=polesp2; RUN;
OBS P VZD POLE UROD96 UROD97
1 0 40 1 57 35 2 0 40 2 58 28 3 0 40 3 . 29 4 0 80 1 57 38 5 0 80 2 58 29 6 0 80 3 56 27 7 0 120 1 49 10 8 0 120 2 54 25 9 0 120 3 53 34 10 25 40 1 53 24 11 25 40 2 45 24 12 25 40 3 46 17 13 25 80 1 54 25 14 25 80 2 50 31 15 25 80 3 48 29 16 25 120 1 63 44 17 25 120 2 57 . 18 25 120 3 53 28 |
Příkaz BY je užitečný také pro spojování dvojic souborů, kde jednomu pozorování v prvním odpovídá několik pozorování ve druhém. Takové situace vznikají tehdy, obsahuje-li jeden soubor údaje specifické pro jednotlivá pozorování a jiný soubor údaje společné celým skupinám pozorování. Zde je příklad: Zkoumáme tři ošetření, každé z nich aplikujeme na 5 subjektů a děláme dvě laboratorní měření. Data vypadají takto:
Chtěli bychom měření standartisovat, tj. odečíst od každé hodnoty MER1 a MER2 průměr přes příslušnou úroveň ošetření. Průměry máme uložené ve zvláštím souboru (v praxi takový získáme třeba jako výstup z PROC MEANS):
Každé pozorování ze souboru PRUMERY tedy odpovídá pěti pozorováním ze souboru MERENI. Nyní potřebujeme spojit data z obou souborů tak, abychom ke každému pozorování znali průměr jeho úrovně ošetření. Použijeme horizontální spojování s příkazem BY, propojovací veličina bude OSETR. Nejdříve musíme oba datové soubory setřídit, pak je spojíme a hned spočteme standardisovaná měření:
Toto je výsledek:
Tento postup funguje, i když propojovací veličina nemá v obou souborech totožné úrovně. Například pokud máme k disposici pouze průměry pro ošetření 1 a 2
můžeme oba soubory spojit jako předtím. Chceme-li mít ve spojených datech pouze pozorování se známými průměry, použijeme argument IN= příkazu MERGE:
Výsledkem je prvních 10 pozorování z předchozího výstupu.
Formátováním v SASu rozumíme zobrazování názvů veličin a jejich hodnot v textových výstupech v uživatelem zvolené podobě. Tím přinutíme SAS namísto kryptografických názvů veličin jako "OSETR" psát srozumitelné "Ošetření" a namísto kódů jako "OSETR=1" nebo "OSETR=2" psát "Radiochemická dekontaminace" nebo "Otesání sekerou". Popisky pro názvy veličin nazýváme značky (labels), pro jednotlivé hodnoty používáme formáty (formats). Formátem rovněž můžeme definovat rozdělení hodnot spojité veličiny do několika skupin a pak používat zformátovanou spojitou veličinu jako faktor. Formáty sloužící ke čtení, nikoli k zápisu, se v SASu nazývají informats.
Značky jsou popisné řetězce přiřazené veličinám. Zavádějí se pro vybrané veličiny během datové procedury příkazem LABEL. Následující data pocházejí z experimentu sledujícího koncentraci chlorofylu v listech trávy ostřice při různých režimech hnojení dusíkem a ošetřování podloží.
Chceme-li použít značky ve výstupu PROC PRINT, musíme přidat argument LABEL:
Formáty řídí zobrazení jednotlivých hodnot v textovém výstupu. Mohou buď předpisovat, jakým způsobem se mají datové hodnoty vypsat (jaká délka řetězců, kolik desetinných míst u reálného čísla, formát den-měsíc-rok pro datum), nebo původní hodnoty nahrazovat pro výstup jinými. Existuje celá řada předdefinovaných formátů, viz
. Nyní si ukážeme, jak zavádět vlastní formáty pro výpis úrovní faktorových veličin. Použijeme PROC FORMAT:Zde jsme zavedli dva formáty zvané DUSREZ a OSPOD. Použijeme-li formát OSPOD pro zápis veličiny, která nabývá hodnot 1-3, zobrazí se místo hodnoty 1 řetězec '2 roky' atd. Formáty určené pro znakové veličiny se definují obdobně, ale jejich jména musí začínat znakem $:
Formáty se přiřazují veličinám příkazem FORMAT uvnitř datové procedury. Přiřaďme tedy formát DUSREZ veličině DUSIK a formát OSPOD veličině OSETR:
Ke jménům formátů v SASových programech se povinně přidává tečka na konec, jinak by SAS předpokládal, že se jedná o jména veličin. Takto vypadá formátovaný výstup z PROC PRINT DATA=ostrice LABEL; RUN; :
V datovém souboru OSTRICE jsou samozřejmě původní hodnoty veličin DUSIK a OSETR, takže chceme-li se omezit na pozorování s režimem hnojení Urea, píšeme:
Datum je v SASu vnitřně representováno jako počet dní od 1. 1. 1960. Potřebujeme-li tady načíst datum do SASového souboru, musíme specifikovat vhodný in-formát, který ho automaticky přepočte. Podobně musíme použít formát při výpisu data ve srozumitelné formě. Pokud chceme použít hodnotu datové veličiny uvnitř programu, například pro výběr pozorování, nezbývá, než používat přímo vnitřní representaci. Tak například všechna pozorování, jejichž datum (čehokoli) padá mezi 12. září 1997 a 16. květen 1998, vybereme takto:
Poněkud elegantněji lze téhož dosáhnout takhle:
Ano, řetězec ve tvaru 'DDmmmYYYY' následovaný ihned znakem d se přeloží jako vnitřní representace tohoto dne. mmm jsou první tři písmena anglického názvu měsíce.
Nyní uveďme příklad na používání formátů a informátů s datem. Napišme datovou proceduru, která přečte datum jako DD/MM/YY a vypíše ho jednak ve vnitřním formátu a jednak jako DDmmmYY.
Informát pro vstup data byl ddmmyy8., po načtení se datum přepočítá na počet dní od 1. 1. 1960 a to se zapíše do veličiny DATUM. Veličina SASDATUM obsahuje totéž. Při výpisu se ovšem pro veličinu DATUM používá formát date8., zatímco veličina SASDATUM se vypisuje tak, jak je. Zde je výsledek:
Počet pozorování je zaznamenán v textových výstupech většiny SASových procedur. Ke stejnému účelu může posloužit i následující makro, které spočítá pozorování a výsledek uschová ve zvolené makro proměnné:
Text makra se píše do okna Program Editoru a makro se zavede pomocí Submit (F8). Chceme-li makro spustit, napíšeme jen
Počet pozorování souboru ANKETA se vypíše do LOG okna.
Datová procedura SASu má většinou následující strukturu:
Příkazy uvnitř se dělí do tří skupin. První skupinu tvoří příkazy jako SET, INPUT, INFILE, MERGE, které se provádějí obvykle hned na začátku. Ve druhé skupině jsou sekvence příkazů manipulující s jednotlivými hodnotami dat, jako transformace, přiřazení, IF, atd. Třetí skupinou jsou příkazy, které se vždy provádějí úplně nakonec, pokud celá procedura proběhne bez chyb. Takové jsou příkazy DROP, KEEP, či RENAME. Rozdíl je v tom, že první a třetí skupina příkazů se provádí jen jednou, buď na začátku nebo na konci, ale druhá skupina příkazů se provádí opakovaně v jakémsi utajeném for-cyklu, který běží přes všechna pozorování. To znamená, že se vezme jedno pozorování ze vstupních dat, provedou se s ním patřičné operace, výsledek se zapíše do výstupního souboru jako jedno pozorování a celý proces se opakuje s dalšími pozorováními, dokud se všechna nevyčerpají.
Proberme si nyní jednoduchý příklad, který do jisté míry ozřejmí některé z principů, vysvětlovaných v předchozím odstavci:
Podívejme se na poslední datovou proceduru. Příkaz SET je příkaz první skupiny: ten načte obsah datového souboru PRVNI. Poslední dva příkazy patří do třetí skupiny a provedou se až nakonec. Uprostřed jsou sevřeny tři příkazy druhé skupiny, které se provádějí v cyklu pro každé pozorování datového souboru PRVNI. Vytvářejí se jimi tři nové veličiny: numerické Y a U a znaková Z. Nově vytvořená veličina se vždy na počátku každého průběhu cyklu iniciuje chybějící hodnotou, kterou representuje tečka . u numerické veličiny a prázdný řetězec "" u znakové. Všimněte si, že veličinám Z a U se přiřazuje jiná hodnota jen někdy, v závislosti na hodnotě veličiny X, potažmo Y. Nedojde-li k přiřazení nebo není-li přiřazení korektní, v datech zůstává chybějící hodnota, jak se můžeme přesvědčit prohlédnutím dat DRUHE:
Všimněte si pátého pozorování: logaritmus záporného čísla se spočítal jako chybějící hodnota, ale ta je vzápětí prohlášena za zápornou. To není od SASu příliš korektní chování! SAS totiž chybějící hodnoty při srovnávání považuje za minus nekonečna. Mohli bychom tento problém obejít, kdybychom napsali IF y<0 AND y<>. THEN z='záporné';
Z tohoto systému zpracování vyplývá řada komplikací a chytáků, které je třeba si uvědomovat. Například v principu záleží na pořadí jednotlivých příkazů uvnitř datové procedury. Proto je dobré dodržovat rozdělení příkazů do oněch tří skupin a nemíchat je mezi sebou.
Jiným důsledkem je, že jednomu pozorování vstupního souboru normálně odpovídá jedno pozorování výstupního souboru. To se ne vždy hodí a pokud to chceme ovlivnit, musíme sami zasáhnout. Zabránit tomu, aby se určité pozorování vypsalo do výstupního souboru, je jednoduché. Stačí napsat prázdnou podmínku jako IF vek>55, nebo explicitně IF vek<=55 THEN DELETE. Naopak, chceme-li na jedno vstupní pozorování generovat několik výstupních, musíme použít klíčové slovo OUTPUT, které vydá pokyn k výpisu jednoho pozorování v tom stavu, v jakém zrovna je.
Protože pozorování se zpracovávají sekvenčně jedno po druhém, vzniká problém, kdykoli potřebujeme mít přístup i k hodnotám jiných pozorování, než je právě to, které zrovna zpracováváme. Máme jenom dva nástroje jak si pomoci: příkaz RETAIN a funkci LAG. Oba jsou diskutovány níže.
Existuje možnost používat cykly různého druhu uvnitř datové procedury. Takový cyklus se normálně provádí vnořeně do onoho implicitního for-cyklu přes všechna pozorování. Ale pokud vytváříme soubor bez jakýchkoli vstupních dat, například simulačně, onen uschovaný implicitní for-cyklus se neprovádí, protože ani není zřejmé, kolik pozorování by měl vytvářet. V takovém případě musíme celý cyklus vytvořit sami uvnitř datové procedury.
Všechny tyto problémy jsou do jisté míry vysvětleny v následujících kapitolách.
Při přípravě dat často potřebujeme počítat například kumulované součty určitých veličin a jiné rekurentní výpočty. Zatím vysvětlené metody to neumožňují, neboť v datové proceduře můžeme normálně pracovat jen s jedním pozorováním a hodnoty ostatních jsou pro nás nedostupné. Řešením tohoto problému je příkaz RETAIN, který umožňuje přenášení hodnot zvolené veličiny na další pozorování. Pracuje se s ním takto:
Příkaz RETAIN c 0 způsobí, že veličina C se inicialisuje při prvním pozorování hodnotou 0 (nikoli chybějící hodnotou jako obvykle) a nadále je u každého dalšího pozorování k disposici její hodnota spočtená při předchozím pozorování. Přičítáme-li k ní tedy hodnotu X, vytváříme kumulativní součty veličiny X. Hle:
Stejnou věc lze spočítat zkratkovým zápisem
SAS to pochopí jako přiřazení veličině C, která se má inicialisovat nulou a přenášet.
Příkaz RETAIN v kombinaci s tříděním SORT je vhodný pro počítání tabulek četností. Vezměme si datový soubor
Rádi bychom znali četnost kvality dojnic a jaká různá hodnocení dojivosti jsou vůbec možná. Nejprve krávy setřídíme:
a teď je spočítáme s použitím přenášených veličin CETNOST a KOLIK a vnitřních veličin FIRST.DOJIVOST a LAST.DOJIVOST:
CETNOST zaznamenává počet krav v dané skupině a KOLIK počítá počet skupin. Výstup pozorování se provádí jen, jde-li o poslední pozorování ve své skupině, takže výsledný soubor bude mít tolik pozorování, kolik je skupin. A takhle to vypadá:
Veličina CISLO zde obsahuje identifikaci poslední nalezené krávy v každé skupině dojivosti.
DO blok je množina příkazů uzavřená mezi klíčovými slovy DO a END. Používá se dvěma způsoby: buď k vložení skupiny příkazů na místo, kde se očekává příkaz jediný, anebo k definování cyklů. První způsob použití nezaslouží víc než prostý příklad:
Cykly se uvnitř datových procedur SASu dají použít v několika variantách:
For cyklus:
DO i = 1 to 4;
<příkazy> END; |
For cyklus přes znakové řetězce:
DO month = 'FEB', 'MAR', 'APR';
<příkazy> END; |
Do-While cyklus
DO WHILE i<n;
<příkazy> END; |
For cyklus s obecným krokem:
DO i = 1 to 10 by 2;
<příkazy> END; |
For cyklus s podmínkou:
DO k =1 to 12 WHILE(month='APR');
<příkazy> END; |
Do-Until Cyklus:
DO UNTIL i>=m;
<příkazy> END; |
For cyklus přes vyjmenované hodnoty:
DO x = 10, 20, 30, 50 to 100 by 5;
<příkazy> END; |
Fungování těchto konstrukcí je zcela zřejmé. Je třeba mít poze na paměti, že probíhají uvnitř každého pozorování zvlášť (vnořené v onom utajeném velkém for-cyklu). Pouze v případě, kdy nenačítáme žádná data, onen velký for-cyklus neprobíhá a my ho sami musíme vytvořit. Zde je příklad simulace: vytvoření tisíce realisací náhodné veličiny s rozdělením chí kvadrát o šesti stupních volnosti:
Vnější cyklus přes N vytváří tisíc pozorování. Veličina CHIKV se iniciuje jako 0 a pak se do ní ve vnitřním cyklu přes I postupně přičítají kvadráty šesti nasimulovaných normálních veličin. Argument funkce RANNOR je seed - počáteční hodnota pro generátor náhodných čísel. Vyhodnocuje se jenom jednou v průběhu celé datové procedury (jinak bychom vygenerovali tisíc totožných chí-kvadrát veličin). Příkaz OUTPUT se provádí na konci každého cyklu přes N a způsobí vytvoření nového pozorování výstupního datového souboru a naplnění všech hodnot jeho veličin. Úplně nakonec vydáváme příkaz uchovat pouze veličinu CHIKV (vytvořili jsme také veličinu ZNORM, ale ta nás vůbec nezajímá). Další použití příkazu OUTPUT je diskutováno v kapitole 3.6.
Podmíněné příkazy tohoto typu slouží k selekci pozorování nebo jejich podmíněnému zpracovávání. Úplná verse této konstrukce je
ačkoli, jak již víme, klausule ELSE je nepovinná a lze ji vynechat. SAS očekává právě jeden příkaz jak za THEN tak za ELSE. Chceme-li podmíněně provádět skupiny více příkazů, musíme je uzavřít mezi DO a END. Zde je příklad:
Konstrukci IF .. THEN .. ELSE je možné řetězit:
Šikovnější příkaz pro takové roztřídění je ovšem SELECT (viz níže).
Konstrukce SELECT nahrazuje sekvenci zřetězených příkazů IF .. THEN .. ELSE prováděných za účelem klasifikace pozorování do skupin. V příkladu na konci předchozí kapitoly se mají pozorování oznámkovat čtyřmi stupni výborně až neprospěl na základě hodnot veličiny SKORE. Namísto tam uvedého řešení můžeme s výhodou využít přehlednější konstrukci
SAS postupně vyhodnocuje podmínky (musí být vypsány v závorkách) jednotlivých příkazů WHEN a jakmile najde první splněnou podmínku, provede příslušný příkaz a konstrukci SELECT opustí. Klausule OTHERWISE je nepovinná. Existuje i druhý způsob použití konstrukce SELECT vhodný jen pro diskrétní veličiny:
Zde se hodnota veličiny uvedené v závorce za příkazem SELECT porovnává s hodnotami, jejichž seznam oddělený čárkami je v závorkách za jednotlivými WHEN klausulemi. Jakmile některá s hodnot souhlasí s hodnotou veličiny, provede se příslušný příkaz a provádění konstrukce SELECT je ukončeno.
Pole v SASu umožňují spojit dohromady několik veličin, nazvat je jedním jménem a přistupovat k nim pomocí indexů. Používají se uvnitř datové procedury, chceme-li si zjednodušit zpracování dat pomocí vnořeného cyklu. Uvažujme třeba tři veličiny X, Y a Z, které mají chybějící hodnoty zakódovány jako 9999. Potřebujeme všechny chybějící hodnoty najít a překódovat na tečky. Můžeme to udělat takto:
To je snadné, pokud máme takové veličiny tři, ale nešikovné, je-li jich pár tuctů. Pak se vyplatí použít pole:
Příkaz ARRAY jmpole{n} vel1 vel2 ... veln; definuje pole nazvané JMPOLE, které má N složek, totiž hodnoty veličin VEL1, ..., VELN (v našem příkladě má pole XYZ tři složky X, Y a Z). Namísto skutečných jmen jednotlivých veličin VEL1, ..., VELN můžeme nadále používat jen jméno pole s příslušným indexem ve složené závorce, tj. JMPOLE{1}, ..., JMPOLE{N}. To nám umožní těchto N veličin zpracovávat v cyklu přes nějakou indexovací proměnnou, jak je vidět na našem příkladě. Poznamenejme ještě, že u veličin pojmenovaných např. X1, X2, ..., X8 můžeme jejich seznam zapsat zkratkou X1-X8, což značně zjednodušuje psaní definice pole.
Kromě plné syntaxe příkazu ARRAY
jsou platné také některé zkrácené zápisy. Například ve
se počet složek pole automaticky určí podle počtu spojovaných veličin. Také můžeme napsat
Tento zápis je ekvivalentní příkazu
tj. vytvoří se automaticky 4 veličiny se jmény tvaru POLEn.
Zde je jiný příklad na použití polí při zpracování dat. Původní data representují longitudinální měření teploty (v časech 0, 15, 30 a 45 dní) pro 15 jedinců rozdělených do tří skupin podrobených různým ošetřením:
Tato data byla připravena pro mnohorozměrnou analýzu pomocí procedury PROC GLM. Lepší metody statistické analysy těchto dat (lineární smíšené modely) však implementuje procedura PROC MIXED, která vyžaduje aby každé pozorování obsahovalo právě jedno měření teploty (s indikací subjektu, kterého se týká a času, kdy bylo učiněno). Potřebujeme tedy datovou strukturu tohoto tvaru:
a tak dále, dohromady 4*15=45 pozorování. Přetransformování dat provede následující datová procedura:
Soubor TEPLOTY2 opravdu má požadovanou strukturu. Všimněte si použití příkazu OUTPUT uvnitř for-cyklu, který způsobí vygenerování čtyř pozorování souboru TEPLOTY2 na každé pozorování souboru TEPLOTY.
Funkce LAG má podobný význam jako příkaz RETAIN, totiž umožnit přístup k hodnotám předchozích pozorování. Její použití je prosté: LAG(X) vrací hodnotu veličiny X z předchozího pozorování, LAG2(X) vrací hodnotu X o dvě pozorování nazpět a tak dále, až LAG100(X) vrací hodnotu o 100 pozorování nazpět. Každý výskyt funkce LAGN (N zastupuje číslo mezi 1 a 100) uvnitř datové procedury vytváří speciální frontu délky N, kterou inicialisuje N chybějícími hodnotami a při každém volání přidá jednu hodnotu na konec fronty a vrátí jednu hodnotu z vršku fronty. Jestliže se funkce LAGN provádí podmíněně (jen pro některá pozorování), uschovává do fronty pouze hodnoty těch pozorování, u nichž byla podmínka splněna. Zde je příklad aplikace na datový soubor TEPLOTY2:
Zde je výsledek (prvních 20 pozorování):
Všimněte si, že LAGTC0 obsahuje hodnotu teploty změřenou na předchozím subjektu v čase 0.
Zde je příklad, jak v jedné datové proceduře třídit pozorování do několika vytvářených datových souborů:
Hodnoty znakové veličiny předěláme na numerické tím, že je přiřadíme numerické veličině. Typ veličin je v SASu určen v okamžiku jejich prvního použití, tj. při prvním přiřazení anebo v příkazu INPUT. Řetězce se též automaticky konvertují na čísla, jsou-li použity v aritmetické operaci.
Zde byla veličina S deklarována v příkazu input jako znaková. Její hodnoty pak byly převedeny do numerické veličiny X (přiřazení X=0 definuje X jako numerickou veličinu). Jiná možnost by byla nahradit dvojici přiřazení x=0; x=s; příkazem x=s+0;.