das stimmt: es muss dynamisiert werden, wenn die Anzahl der Versicherten und der Versicherungsleistungen nicht bekannt oder zu zahlreich für die manuelle Eingabe sind und sich der Zeitraum über mehrere Jahre erstreckt. Die Abfrage des Arrays wird dann etwas unübersichtlich. Aber, Alostcause, keine Angst, es sieht schlimmer aus, als es ist. An Arrayverarbeitung tastet man sich langsam (mit ein paar Beispieldatensätzen) heran. Nur Mut!
Die Anzahl der Versicherten, der Versicherungsleistungen und der Jahre bestimmt die Größe der jeweiligen Dimension des Arrays und kann über Makrovariablen im Vorfeld bereitgestellt werden. Dazu nutzt man die Proc SQL.
Für das Retain-Statement braucht man die Anzahl aller Arrayelemente (Multiplikation aller Dimensionen), die berechnet man in einem Data-null-Step und übergibt auch dieses Ergebnis in eine Makrovariable.
Wenn der Zeitraum über mehr als ein Jahr geht, braucht das Array "versleist" eine zusätzliche Dimension. Es hat damit 4 Dimensionen: Versicherter, Versicherungsleistung, Jahr, Monat. Bei der Verarbeitung der Datensätze kann man dann leider nicht mehr von Monat-Start bis Monat-Ende laufen. Wenn die Leistung Mitte 2015 beginnt und Mitte 2017 endet, sind alle Monate aus 2017 betroffen. Also läuft die Schleife über die kompletten Jahre von Start und Ende und prüft, ob der jeweilige Monat tatsächlich im Zeitraum liegt.
Makrovariablen haben eine maximale Größe von 65534 Zeichen. Wenn das für die Versicherten nicht reicht (&alle_versicherten), muss das Array - wie im Beispiel oben - mit sort und by-Verarbeitung für jeden einzelnen (first.versicherter) im Datastep versorgt werden.
dm 'cle log';
data daten;
versicherter = 12345; leistung = 'a'; start = '15Jan2016'd; ende = '17Aug2016'd; betrag = 400; output;
versicherter = 12345; leistung = 'a'; start = '01Oct2016'd; ende = '31Dec2016'd; betrag = 200; output;
versicherter = 12345; leistung = 'b'; start = '01Feb2016'd; ende = '14Jun2016'd; betrag = 150; output;
versicherter = 11111; leistung = 'a'; start = '01Jan2016'd; ende = '17Nov2016'd; betrag = 500; output;
versicherter = 11111; leistung = 'b'; start = '16Jul2016'd; ende = '31Aug2016'd; betrag = 55; output;
format start ende eurdfdd10.;
run;
* Ermittlung Anzahl Versicherter + Leistungen, betroffene Jahre;
proc sql noprint;
select count(distinct versicherter) into :n_v
from daten;
select count(distinct leistung) into :n_l
from daten;
select distinct quote(leistung) into :alle_leistungen separated by ', '
from daten;
select distinct versicherter into :alle_versicherten separated by ', '
from daten;
select min(year(start)) into :min_jahr
from daten;
select max(year(ende)) into :max_jahr
from daten;
quit;
%put &=n_v &=n_l &=min_jahr &=max_jahr;
%put &=alle_leistungen;
%put &=alle_versicherten;
* Ermittlung Anzahl Arrayelemente (Anzahl Versicherte * Anzahl Leistungen * Anzahl Jahre * 12 Monate);
data _null_;
anzahl = &n_v. * &n_l. * sum(&max_jahr., -&min_jahr., 1) * 12;
call symputx('ae',anzahl);
run;
%put &=ae;
data anz_v (keep=versicherter anz_v)
anz_av (keep=anz_av)
anz_al (keep=versicherter anz_al)
anz_vl (keep=anz_vl);
retain versleist1-versleist&ae.; * alle Arrayelemente;
set daten end=letzter;
array leist (&n_l.) $1 _temporary_ (&alle_leistungen.); * Leistungen;
array vers (&n_v.) _temporary_ (&alle_versicherten.); * Versicherte;
array versleist(&n_v.,&n_l.,&min_jahr.:&max_jahr.,12); * 4 Dimensionen: Versicherter, Leistung, Jahr, Monat;
* Position des Versicherten im Array;
do i=1 to dim(vers) until (posvers);
if versicherter = vers(i) then posvers = i;
end;
* Position der Leistung im Array;
do i=1 to dim(leist) until (posleist);
if leistung = leist(i) then posleist = i;
end;
* Array versleist erhält an der Position des betroffenen Monats eine 1 (alternativ den Betrag);
do jahr=year(start) to year(ende);
do monat=1 to 12;
* Monatsfeld fällt in den Zeitraum: Ende des Monats ist >= Start und Beginn des Monats <= Ende;
if intnx('month',mdy(monat,1,jahr),0,'end') >= start and intnx('month',mdy(monat,1,jahr),0,'beginning') <= ende
then versleist(posvers, posleist, jahr, monat) = 1;
end;
end;
* am Ende Array auswerten, Fragen beantworten;
if letzter then do;
* Fragen 1;
anz_av = sum(of versleist[*]); * Anzahl Monate aller Versicherten;
output anz_av;
* Frage 2;
do v=1 to &n_v.;
anz_v = .; * Anzahl Monate je Versichertem;
do l=1 to &n_l.;
do j=&min_jahr. to &max_jahr.;
do m=1 to 12;
anz_v = sum(anz_v, versleist(v, l, j, m));
end;
end;
end;
versicherter = vers(v); * Ausgabe je Versicherter;
output anz_v;
end;
* Fragen 3: in wieviel Monaten haben alle Versicherten mind. 1 Leistung bezogen?;
do j=&min_jahr. to &max_jahr.;
do m=1 to 12;
anz_vl_temp = .;
do v=1 to &n_v.;
anz_l_temp = .;
do l=1 to &n_l.; * irgend eine Leistung im Monat?;
if versleist(v, l, j, m)=1 then anz_l_temp = 1;
end;
* die Anzahl der Versicherten mit mind. 1 Leistung in diesem Monat erhöht sich um 1;
if anz_l_temp then anz_vl_temp = sum(anz_vl_temp,1);
end;
* die Anzahl der Versicherten mit Leistung in diesem Monat entspricht der Zahl aller Versicherten;
if anz_vl_temp = dim(vers) then anz_vl = sum(anz_vl, 1);
end;
end;
output anz_vl;
* Frage 4: wieviele Monate haben die Versicherten sowohl Leistung 1 als auch 2 bezogen?;
do j=&min_jahr. to &max_jahr.;
do v=1 to 2;
do m=1 to 12;
anz_al = sum(anz_al, (versleist(v, 1, j, m)=1 and versleist(v, 2, j, m)=1)); * Anzahl Monate mit Leistung 1 und Leistung 2;
end;
versicherter = vers(v);
output anz_al;
end;
end;
end;
run;
... View more