LesezeichenAbonnierenRSS-Feed abonnieren
Alostcause
Explorer | Level 4

Hallo ihr alle!

 

Ich bin ein absoluter SAS-Frischling und bearbeite grade einen größeren Datensatz (um die 500.000 Zeilen) mit Daten für die Inanspruchnahme von verschiedenen Pflegeleistungen. Eine Zeile ist ein Fall, aber nicht zwangsweise eine Person (manche haben mehrere Zeilen, da mehrere Leistungen oder zu verschiedenen Zeiträumen).

Was mich nun interessiert ist zu gucken, für wie viele Monate bestimmte Pflegeleistungen insgesamt in Anspruch genommen wurden. Über proc freq sehe ich nur die Anzahl der Zeilen, in denen die Leistung steht (sind alle codiert in einer Spalte aufgelistet). Ich sehe aber nicht, wie lange die Leistungen konsumiert wurden (einige haben sie für 10 Monate innerhalb einer Zeile bekommen, andere nur für 2 Monate. Proc freq gibt mir insgesamt allerdings nur eine 2 an, die wenig aussagekräftig ist).

 

Ich habe es schon mit intck probiert, bin aber scheinbar zu unfähig dafür mein Vorgehen war nun das folgende:

 

data Name Datensatz;

months = intck('month','01Jan2016'd,'01Jan2017'd);

run;

 

Als Ergebnis spuckt mir SAS selbstverständlich "months = 12" aus. Wenn ich nun allerdings schreibe

data Name Datensatz;

months = intck('month','01Jan2016'd,'01Jan2017'd);

where Pflegeleistung = NameLeistung;

run;

 

Bekomme ich nur einen Error in der Syntax, dass "where" nicht definiert sei. Habt ihr eine Idee, wie ich SAS dazu bekomme, mir zu sagen, wie viele Monate lang meine Leistung X innerhalb meiner 500.000 Zeilen bezogen wurde?

 

 

Dankeschön und sorry für die höchstwahrscheinlich total dumme Frage 😄

9 ANTWORTEN 9
CKothenschulte
Obsidian | Level 7

Hallo @Alostcause,

 

es gibt keine dummen Fragen!

 

Was möchten Sie denn erreichen?

Ich habe mal eine kleine Testtabelle erstellt:

data DATENSATZ;
input
  LEISTUNG $1.
  START date10.
  ENDE date10.;

cards;
a 01jan2018 01jan2019
a 01feb2018 01mar2019
b 01mar2018 01may2019
;
run;

Die Leistungen heißen bei mir "a" und "b".

 

 

Mit dem WHERE-Statement kann man auf bestimmte Ausprägungen filtern.

Obacht: Nur diese werden dann in die Ausgabetabelle übernommen!

data NameDatensatz;
set DATENSATZ;

MONATE = intck('month',START,ENDE);

where LEISTUNG = 'a';

run;

 

 

Mein kleines Beispielprogramm funktioniert, übernimmt nur die beiden Datensätze mit Leistung gleich "a" und rechnet die Anzahl Monate zwischen Start und Ende aus.

 

Wenn alle Datensätze übernommen werden sollen, jedoch nur für Leistung gleich "a" gerechnet werden soll, kann man das mit einem einfachen IF lösen:

data NameDatensatz;
set DATENSATZ;

if Leistung = 'a' then
  MONATE = intck('month',START,ENDE);

run;

 

Wenn es weitere Fragen gibt: Gerne melden!

Alostcause
Explorer | Level 4

Dankeschön für die fixe Antwort!

Klappt leider noch nicht so ganz (SAS spuckt mir die komplette Starttabelle aus und auch im Log steht nichts zu den Monaten, die diese Leistung a nun bezogen wurde. Aber immerhin gibt's auch keine Fehlermeldungen).

 

Meine Tabellenzeilen sind wie folgt aufgebaut:

Versichertenid 12345 | Leistung a | Start der Leistung 15Jan2016 | Ende der Leistung 17Aug2016 | Betrag 400€

Versichertenid 12345 | Leistung a | Start der Leistung 01Oct2016 | Ende der Leistung 31Dec2016 | Betrag 200€

Versichertenid 12345 | Leistung b | Start der Leistung 01Feb2016 | Ende der Leistung 14Jun2016 | Betrag 150€

Versichertenid 11111 | Leistung a | Start der Leistung 01Jan2016 | Ende der Leistung 17Nov2016 | Betrag 500€

Versichertenid 11111 | Leistung b | Start der Leistung 16Jul2016 | Ende der Leistung 31Aug2016 | Betrag 55€

usw.

 

Ich habe also zum einen das Problem, dass einige Versicherte Leistung a über 2-x voneinander getrennte Zeiräume bezogen haben (siehe Versicherter 12345) und zum anderen dass die Bezugszeiträume überall unterschiedlich groß sind.

 

Für mich relevant ist nun zu wissen:

1. Wie viele Monate Leistung a/b/c/d .... insgesamt einzeln von allen Versicherten genutzt wurde --> Wie lang haben Versicherter 11111 und 12345 insgesamt Leistung a bezogen in 2016?

2. Wie viele Monate Leistung a/b/c/d .... insgesamt einzeln von jedem individuellen Versicherten genutzt wurde --> Wie lang hat Versicherter 12345 insgesamt Leistung a bezogen in 2016?

3. Wie viele Monate Leistung a ZEITGLEICH mit Leistung b/c/d... insgesamt von allen Versicherten genutzt wurde --> Wie lang haben Versicherter 11111 und 12345 insgesamt in 2016 zum gleichen Zeitpunkt jeweils Leistung a und Leistung b bezogen?

4. Wie viele Monate Leistung a ZEITGLEICH mit Leistung b/c/d... insgesamt von jedem individuellen Versicherten genutzt wurde --> Wie lang hat Versicherter 12345 insgesamt in 2016 zum gleichen Zeitpunkt Leistung a und Leistung b bezogen?

CKothenschulte
Obsidian | Level 7

Okay, das sind ja mal konkrete Fragen Smiley (fröhlich)

 

Ich habe meine Testtabelle um zwei Versicherte erweitert:

data DATENSATZ;
input
  VERSICHERTER 2.
  LEISTUNG $2.
  START date10.
  ENDE date10.;

MONATE = intck('month',START,ENDE);

cards;
01 a 01jan2018 01jan2019
01 a 01feb2018 01mar2019
01 b 01mar2018 01may2019
02 a 01jan2018 01mar2019
02 b 01apr2018 01may2019
;
run;

Die Berechnung der Monate habe ich der Übersichtlichkeit wegen direkt im selben Data-Step gemacht.

 

 

Die Fragen 1 und 2 lassen sich recht einfach jeweils über die Prozedur MEANS lösen:

Frage 1:

proc means data=Datensatz nway noprint;

   var MONATE;
   class LEISTUNG;

   output out=JE_LEISTUNG (drop=_type_ _freq_)  sum=MONATE;

run;

 

Frage 2:

(Erweiterung Frage 1 um eine CLASS-Variable)

proc means data=Datensatz nway noprint;

   var MONATE;
   class VERSICHERTER LEISTUNG;

   output out=JE_VERSICHERTER (drop=_type_ _freq_)  sum=MONATE;

run;

 

Die Fragen 3 und 4 lassen sich, glaube ich, nur komplizierter durch echtes Ausprogrammieren lösen.

Erste Idee: Je Versichertem und je (Kalender-)Monat ermitteln, ob Leistung a, b, c, ... bezogen wurde.

Oder muss das taggenau betrachtet werden? Abhängig von der Anzahl Leistungen muss man das auch generisch lösen.

Mit zwei Ausprägungen in unseren Testdaten ist das schnell gemacht. Vermutlich gibt es aber deutlich mehr...

 

Jetzt erstmal: Schönes Wochenende!

 

Ich hoffe, meine Antwort hilft fürs Erste weiter.

mfab
Quartz | Level 8

Hallo @Alostcause,

 

interessante Fragestellung 🙂

 

Die Fragen 1 und zwei sind ja recht leicht zu beantworten - hier möchte ich nicht darauf eingehen.

Zu Frage 3 und 4 möchte ich noch einen anderen Ansatz bieten.

 

Für mich relevant ist nun zu wissen:

1. Wie viele Monate Leistung a/b/c/d .... insgesamt einzeln von allen Versicherten genutzt wurde --> Wie lang haben Versicherter 11111 und 12345 insgesamt Leistung a bezogen in 2016?

2. Wie viele Monate Leistung a/b/c/d .... insgesamt einzeln von jedem individuellen Versicherten genutzt wurde --> Wie lang hat Versicherter 12345 insgesamt Leistung a bezogen in 2016?

3. Wie viele Monate Leistung a ZEITGLEICH mit Leistung b/c/d... insgesamt von allen Versicherten genutzt wurde --> Wie lang haben Versicherter 11111 und 12345 insgesamt in 2016 zum gleichen Zeitpunkt jeweils Leistung a und Leistung b bezogen?

4. Wie viele Monate Leistung a ZEITGLEICH mit Leistung b/c/d... insgesamt von jedem individuellen Versicherten genutzt wurde --> Wie lang hat Versicherter 12345 insgesamt in 2016 zum gleichen Zeitpunkt Leistung a und Leistung b bezogen?

 

Frage 3 lässt sich nach Lösung von Frage 4 beantworten, wenn man die Ergebnisse für die individuellen Versicherten hat, kann man diese aufsummieren.

Insofern bleibt Frage 4, die ich nochmals genauer spezifizieren würde.

Vermutlich wird die Summe der Zeiträume gesucht, zu denen jeweils Leistung a und eine beliebige andere Leistung überlappend in Anspruch genommen wurde. (nach meinem Verständnis "gleichzeitig").

 

Alternativ könnte man auch ermitteln, welche Leistungen mit gleicher Zeitdauer genutzt wurden (nach meinem Verständnis "zeitgleich"). Wenn also in 2015 Leistung a 3 Monate lang genutzt wurde und Leistung b in 2016 3 Monate lang genutzt wurde wäre dies zeitgleich.

 

Die dritte Option wäre unterschiedliche Leistungen zu suchen, die exakt zum gleichen Zeitraum genutzt wurden. Also Leistung a exakt vom 01.01.2018 bis 01.05.2018 und Leistung b ebenfalls exakt von 01.01.2018 bis 01.05.2018.

 

Vermutlich wird für die erste Variante eine Lösung auf Tagesbasis gesucht. Also wieviele Tage wurde Leistung a mit einer beliebigen anderen Leistung genutzt. Wenn man noch mehr Details haben will, könnte man auch exakt aufsplitten, wie die Überschneidungen pro Leistung sind.

 

Meine Idee wäre hier die Leistungen in separate Tabelle aufzuspalten und anschliessend über die Bezugszeiträume als Gültigkeiten zu joinen. Über eine entsprechende Berechnung kann ich die Anzahl Tage ermitteln und anschliessend aufsummieren.

Das Ganze in einem Macro für die möglichen Kombinationen mit abschliessender Zusammenführung der Ergebnisse.

 

Dies würde ich gegenüber der Lösung mit Arrays bevorzugen - aufgrund der Übersichtlichkeit und der Möglichkeit zum Debugging. Aber das ist sicherlich eine individuelle Entscheidung.

 

Nachfolgend mal ein schnelles Beispiel: (mit der Annahme, dass die Ausgangstabelle schon auf ein bestimmtes Jahr eingeschränkt ist. Ansonsten müsste man die Verarbeitung noch erweitern und die Auszählung für unterschiedliche Jahre trennen. Z.B. mit einem weiteren Data-Step)

 



data datensatz;
input
  versicherter 5.
  leistung $2.
  start date10.
  ende date10.;
format start ende date10.;
tage = ende-start;
cards;
12345 a 15jan2016 17aug2016
12345 a 01oct2016 31dec2016
12345 b 01feb2016 14jun2016
11111 a 01jan2016 17nov2016
11111 b 16jul2016 31aug2016
;
run;

/* Ermittlung Anzahl Leistungen */
proc sql noprint;
select count(distinct leistung) into :anz_leistungen from datensatz;
select distinct leistung into :leistungen separated by ' ' from datensatz;
quit;

data ergebnistabelle;
  length versicherter 8
         kriterium $10.
		 tage_ueberschneidung 8;
stop;
run;


%macro berechnung;

%do i = 1 %to &anz_leistungen;
%put i = &i.;
%let leistung = %scan(&leistungen,&i);
%put leistung = &leistung.;
data basis
     vergleich;
 set datensatz;
 if leistung = "&leistung." then output basis;
 else output vergleich;
run;

/* Annahme: alle Datensätze in basis und vergleich sind pro Versichertem und Leistung hinsichtlich Zeitraum überschneidungsfrei */
proc sql;
create table zwischenschritt as
select a.versicherter,
       "&leistung. mit x" as kriterium length = 10,
       sum(-max(a.start, b.start), min(a.ende, b.ende)) as tage_ueberschneidung
  from basis a, vergleich b
 where ((b.start between a.start and a.ende)
      or (b.ende between a.start and a.ende)
      or (b.start le a.start and b.ende ge a.ende) 
       )
   and a.versicherter = b.versicherter
;
quit;

proc append base=ergebnistabelle data=zwischenschritt;
run;

%end; /* anz_leistungen */

%mend berechnung;

%berechnung;


proc means data=ergebnistabelle nway noprint;
var tage_ueberschneidung;
class versicherter kriterium;
output out=ergebnis_versicherte (drop=_type_ _freq_) sum=tage_ueberschneidung;
run;

proc means data=ergebnistabelle nway noprint;
var tage_ueberschneidung;
class kriterium;
output out=ergebnis_kriterium (drop=_type_ _freq_) sum=tage_ueberschneidung;
run;

 

Schöne Grüsse

Michael 

 

p.s.: sorry, ich habe auf einen bestimmten Beitrag geantwortet, daher ist mein Beitrag wohl im Verlauf dazwischen gerutscht. Ich bitte die Unordnung zu entschuldigen.

jh_ti_bw
Obsidian | Level 7

Hallo Alostcause,

 

ich würde SQL verwenden. Da kann man gleichzeitig die Selektionen der Datensätze vornehmen und aggregieren. Mir ist noch nicht klar, was Du mit "Monaten" meinst. Am Beispiel 15.01 - 14.02

  • Ist das 1 Monat?
  • Sind das 2. Monate (Januar und Februar)?
  • ist das kein Monat (weder ein voller Januar noch ein voller Februar)?

Gegebenenfalls muss man die Monatsberechnung und Selektion noch anpassen.

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;

Proc sql;
    Create table Erg2 as 
    select versicherter
    , Leistung
    , sum (intck('month',start,ende)) as monate
    from Daten
    group by versicherter
    , leistung
    ;
    Create table Erg1 as 
    select versicherter
    , sum (monate) as monate
    from Erg2
    group by versicherter
    ;
    Create table Erg4 as 
    select Coalesce(t1.versicherter, t2.versicherter) as versicherter
    , t1.leistung as leistung1
    , t2.leistung as leistung2
    , sum (intck('month',Max(t1.start, t2.start),Min(t1.ende, t2.ende))) as monate
    from Daten as t1, Daten as t2
    where   t1.versicherter = t2.versicherter
        and t1.leistung < t2.leistung
        and (t1.start < t2.ende and t1.ende > t2.start) /* Edit: Fehlerkorrektur */
    group by calculated versicherter
    , t1.leistung
    , t2.leistung
    ;
    Create table Erg3 as 
    select leistung1
    , leistung2
    , sum (monate) as monate
    from erg4
    group by leistung1
    , leistung2
    ;
quit;

Viele Grüße

Jan

 

HeideTribius
Fluorite | Level 6

hallo Alostcause,

 

nicht nur für einen SAS-Frischling dürfte die Aufgabenstellung eine echte Herausforderung sein. Mit intck ist es nicht zu lösen, weil Du den Querverweis/Verarbeitung zwischen den Datensätzen brauchst. 

M.E. kannst Du das Problem nur lösen, indem Du ein dreidimensionales Array anlegst (eine Dimension je Versicherter, Leistung, Monat). Dann verarbeitest Du die Datensätze und schreibst in den betroffenen Monat eine 1 (oder den Betrag, falls damit noch etwas geschehen soll). Am Ende wertest Du das Array aus und lässt Dir Deine Fragen beantworten. (die waren mir nicht ganz klar, lassen sich aber durch die Gestaltung der Schleifen beliebig definieren).

 

Sollen die Werte einer Variablen durch die Datensätze hindurchgereicht werden, müssen sie mit retain vor der Initialisierung beim Einlesen eines neuen Datensatzes "gerettet" werden.

Ich bin davon ausgegangen, dass die Versicherungsleistungen bekannt sind und der Zeitraum ausschließlich ein Jahr betrifft. 

Abkürzungen: v=Versicherter, l=Leistung, m=Monat.

 

 

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;

* Sortieren nach Versicherten;
proc sort data=daten;
   by versicherter leistung;
run;


data  anz_v  (keep=versicherter anz_v)
      anz_av (keep=anz_av)
      anz_al (keep=versicherter anz_al)
      anz_vl (keep=anz_vl);
retain posvers                         /* Position des Versicherten im Array der Versicherten */
       versleist1-versleist48;          * Arrayelemente für 2 Versicherte und 2 Leistungen;
   set daten end=letzter;
   by versicherter;

   array leist (2) $1 _temporary_ ('a', 'b');      * 2 Leistungen (sind vorher bekannt);
   array vers  (2)    _temporary_;                 * 2 Versicherte;
   array versleist(2,2,12);                        * 3 Dimensionen: Versichertert, Leistung, Monate in 2016;

   if first.versicherter then do;
      posvers +1;
      vers(posvers) = versicherter;
   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 Monats eine 1 (alternativ den Betrag);
   do monat=month(start) to month(ende);
      versleist (posvers, posleist, monat) = 1; 
   end;

   if letzter then do;
      * Fragen 1 und 2;
      anz_av = .;                    * Anzahl Monate aller Versicherten;
      do v=1 to 2;
         anz_v = .;                  * Anzahl Monate je Versichertem;
         do l=1 to 2;
            do m=1 to 12;
               anz_v  = sum(anz_v,  versleist(v, l, m));
               anz_av = sum(anz_av, versleist(v, l, m));
            end;
         end;
         versicherter = vers(v);
         output anz_v;
      end;
      output anz_av;

      * Fragen 3: in wievielen Monaten haben alle Versicherten gleichzeitig Leistungen bezogen?;
      do m=1 to 12;
         anz_vl_temp = .; 
         do v=1 to 2;
            anz_vl_temp = sum(anz_vl_temp, versleist(v, 1, m)=1 or versleist(v, 2, m)=1);
         end;
         if anz_vl_temp = dim(vers) then anz_vl = sum(anz_vl, 1);
      end;
      output anz_vl;

      * Frage 4: in wievielen Monate haben die Versicherten sowohl Leistung 1 als auch 2 bezogen?;
      do v=1 to 2;
         do m=1 to 12;
            anz_al = sum(anz_al, (versleist(v, 1, m)=1 and versleist(v, 2, m)=1));   * Anzahl Monate mit Leistung 1 und Leistung 2;
         end;
         versicherter = vers(v);
         output anz_al;
      end;
   end;
run;

 

Heide

HeideTribius
Fluorite | Level 6

Nachtrag: für die Beantwortung der Frage nach der Anzahl Monate aller Versicherten, aller Leistungen braucht man keine Schleife zu durchlaufen. Es reicht:

 anz_av = sum(of versleist[*]);
CKothenschulte
Obsidian | Level 7

Hallo @HeideTribius,

 

tolle Lösung!

Ungefähr so meinte ich "ausprogrammieren" Smiley (zwinkernd)

 

Interessant, wie einem doch Arrays immer wieder helfen.

 

In den echten Daten gibt es vermutlich viel mehr Leistungen, Versicherte und vermutlich auch Zeiträume.

Da muss die Lösung dann noch "dynamisiert" werden.

HeideTribius
Fluorite | Level 6

 

 

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;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Diskussionsstatistiken
  • 9 Antworten
  • 1945 Aufrufe
  • 11 Kudos
  • 5 in Unterhaltung