LesezeichenAbonnierenRSS-Feed abonnieren
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Margaretha_97
Fluorite | Level 6

Hallo liebe Mitglieder,

 

im Rahmen einer Forschungsarbeit programmiere ich mit SAS 9.4 um an bestimmte Daten zu kommen, die ich dann im Anschluss weiter auswerten kann.

 

Ich zähle dabei die Kombinationen von verschiedenen Diagnosen (ICD-Code, z.B. M84.11) und Prozeduren/Operationen (OPS-Code, z.B. 5782), sodass ich jeweils die Verknüpfung aus jeweils einem ICD- und einem OPS-Code angezeigt bekomme.Die Syntax läuft auch problemlos.

 

Nun kann es jedoch auch sein, dass ein Patient mit einer bestimmten Diagnose (ICD-Code) mit mehreren verschiedenen Operationen (OPS-Code) behandelt werden kann.

Mögliche Kombinationen wären in meinem Fall beispielseise:

- die Diagnose M84.11 + die Operationen 5-782 + 5-784

- die Diagnose M84.12 + die Operationen 5-782 + 5-784 + 5-785.

 

Ich habe unter anderem schon gelesen, dass so etwas mit der panel-ID möglich ist. Leider komme ich aber nicht weiter und bin mir sehr unsicher, wie ich diese Kombinationsabfrage programmieren kann.

 

Meine bisherige Syntax sieht so aus und funktioniert problemlos:

/*** Makros f?r Pfade																								  ***/
%let datenpfad	= C:\Users\Margaretha\Desktop\SBA\DRG\Data;
%let outputpfad = C:\Users\Margaretha\Desktop\SBA\DRG\Data;

/*** Makros f?r Datei- und Outputnamen																				  ***/
%let outputname = output20200717; 	


/*** Libname vergeben																								  ***/
libname daten "&datenpfad";  

ods html file = "&outputpfad./&outputname..html";

%macro auswertung (ops, icd, icdsteller);

%do year = 2007 %to 2016; 

*Zusammenfassung der OPS-Codes in einer Variable;
*find(x,y,z) schaut in Variable x nach dem String y an z-ter Position;
*d.h. es werden alle OPS mit '5782' ab der 1.Stelle gefunden, also bspw. auch 57820t;
*OPS_Gesamt nimmt den Wert 1 an, wenn in den Spalten ops_ko der gesuchte Code vorkommt;

data tab_&ops._&icd.; 
set daten.drg&year._3846_sf (keep= icd_hd ops_ko:);
    
	OPS_Gesamt = 0;
  	
	%do i = 1 %to 101; 
	If substr(ops_ko&i,1,4) ="&ops." then OPS_Gesamt = 1;
    %end;

*Filterung der Daten nach der gew?nschten ich_hd;
*ICD_Gesamt nimmt den Wert 1 an, wenn in der Spalte icd_hd der gesuchte Code vorkommt;


	ICD_Gesamt = 0;

	if substr(icd_hd,1,&icdsteller.) = "&icd." then ICD_Gesamt = 1;

*Erstellen einer Tablle, die die Kombination aus gew?nschtem OPS-Code und ICD-Code enth?lt;

proc freq data=tab_&ops._&icd. ;
title "H?ufigkeit nach &icd. und &ops. f?r das Berichtsjahr &year.";
  tables icd_hd;
  where OPS_Gesamt = 1 AND ICD_Gesamt = 1;
run;


%end;
%mend auswertung;
%auswertung (5782, M8411, 5);
%auswertung (5782, M8412, 5);
%auswertung (5782, M8413, 5);
%auswertung (5782, M8414, 5);
%auswertung (5782, M8415, 5);
%auswertung (5782, M8416, 5);
%auswertung (5782, M8417, 5);

%auswertung (5784, M8411, 5);
%auswertung (5784, M8412, 5);
%auswertung (5784, M8413, 5);
%auswertung (5784, M8414, 5);
%auswertung (5784, M8415, 5);
%auswertung (5784, M8416, 5);
%auswertung (5784, M8417, 5);

%auswertung (5785, M8411, 5);
%auswertung (5785, M8412, 5);
%auswertung (5785, M8413, 5);
%auswertung (5785, M8414, 5);
%auswertung (5785, M8415, 5);
%auswertung (5785, M8416, 5);
%auswertung (5785, M8417, 5);

ods html close;

Ich hoffe, ich konnte meine Fragestellung verständlich formulieren. Über Anregungen oder Hilfestellungen wäre ich sehr dankbar!

 

Allen ein schönes Wochenende und liebe Grüße 🙂

1 AKZEPTIERTE LÖSUNG

Akzeptierte Lösungen
FreelanceReinh
Jade | Level 19

Hallo @Margaretha_97,

 


@Margaretha_97  schrieb:
...
	OPS_Gesamt = 0;
  	
	%do i = 1 %to 101; 
	If substr(ops_ko&i,1,4) ="&ops." then OPS_Gesamt = 1;
    %end;
...

Der obige Abschnitt des bestehenden Makros könnte u. U. wie folgt vereinfacht werden:

array ops_ko[101];
OPS_Gesamt = ("&ops." in: ops_ko);

Dadurch würden die Initialisierung von OPS_Gesamt und 101 IF-THEN-Statements im generierten Datastep-Code durch eine einzige Zuweisung und eine Array-Deklaration ersetzt. Voraussetzung ist, dass die definierte Länge der Variablen ops_ko1-ops_ko101 mindestens so groß ist wie die Länge der zu suchenden Strings "&ops.". (EDIT: Ferner darf es keine Variable ops_ko ohne Nummer im Input-Dataset geben; ggf. einfach das Array anders nennen.) Da die 101 Variablen vermutlich alle gleich lang definiert sind und man keinen längeren String in kürzeren Variablen suchen wird, dürfte das gegeben sein. Der Operator IN: prüft dann, ob mindestens eines der Array-Elemente mit der angegebenen Zeichenfolge beginnt. Wenn ja, wird OPS_Gesamt auf 1 gesetzt, sonst auf 0.

 

Ausgehend von dieser Vereinfachung können wir die Bedingung so erweitern, dass die Makrovariable ops auch eine ganze Liste von OPS-Codes enthalten darf, getrennt etwa durch Leerzeichen, und dass jedes Element der Liste am Anfang mindestens einer der 101 Variablen des Arrays gefunden werden muss (wenn das der Inhalt der "Kombinationsabfrage" sein soll):

OPS_Gesamt = 1
%do i=1 %to %sysfunc(countw(&ops,%str( )));
  & "%scan(&ops,&i,%str( ))" in: ops_ko
%end;
;

Die %DO-Schleife durchläuft alle durch Leerzeichen begrenzten "Wörter" in &ops und erzeugt für jedes "Wort", also jeden OPS-Code, eine mit UND verknüpfte Bedingung wie oben. Der UND-Operator (&) ist wegen der vorangestellten 1 (=WAHR) auch am Anfang korrekt. Das Semikolon ganz unten schließt die Zuweisung im Datastep ab. Der Code funktioniert auch mit einem einzelnen OPS-Code in &ops wie zuvor.

 

Es ist gute Praxis (um mögliche Namenskonflikte zu vermeiden), die Laufvariable i als lokal zu deklarieren, also weiter oben im Makro die Zeile

%local i;

einzufügen (oder auch gleich %local i year;).

 

Problematisch ist nur die Verwendung von &ops im Dataset-Namen tab_&ops._&icd., denn darin dürfen keine Leerzeichen vorkommen und bei langen OPS-Code-Listen könnte zudem die maximale Länge (32) von Dataset-Namen überschritten werden (auch bei Verwendung von Unterstrichen statt Leerzeichen als Trennzeichen). Ich würde die Komponente &ops. daher möglichst aus dem Namen herauslassen. Die Datasets scheinen ja sowieso nur temporär für die Auswertung mit PROC FREQ angelegt zu werden. Insbesondere werden die Datasets für 2007 bis 2015 jeweils durch das Dataset des Folgejahres überschrieben.

 

Die Makro-Aufrufe könnten dann etwa so aussehen:

%auswertung (5782 5784, M8411, 5)
%auswertung (5782 5784 5785, M8412, 5)
%auswertung (5785, M8417, 5)

 

Lösung in ursprünglichem Beitrag anzeigen

2 ANTWORTEN 2
FreelanceReinh
Jade | Level 19

Hallo @Margaretha_97,

 


@Margaretha_97  schrieb:
...
	OPS_Gesamt = 0;
  	
	%do i = 1 %to 101; 
	If substr(ops_ko&i,1,4) ="&ops." then OPS_Gesamt = 1;
    %end;
...

Der obige Abschnitt des bestehenden Makros könnte u. U. wie folgt vereinfacht werden:

array ops_ko[101];
OPS_Gesamt = ("&ops." in: ops_ko);

Dadurch würden die Initialisierung von OPS_Gesamt und 101 IF-THEN-Statements im generierten Datastep-Code durch eine einzige Zuweisung und eine Array-Deklaration ersetzt. Voraussetzung ist, dass die definierte Länge der Variablen ops_ko1-ops_ko101 mindestens so groß ist wie die Länge der zu suchenden Strings "&ops.". (EDIT: Ferner darf es keine Variable ops_ko ohne Nummer im Input-Dataset geben; ggf. einfach das Array anders nennen.) Da die 101 Variablen vermutlich alle gleich lang definiert sind und man keinen längeren String in kürzeren Variablen suchen wird, dürfte das gegeben sein. Der Operator IN: prüft dann, ob mindestens eines der Array-Elemente mit der angegebenen Zeichenfolge beginnt. Wenn ja, wird OPS_Gesamt auf 1 gesetzt, sonst auf 0.

 

Ausgehend von dieser Vereinfachung können wir die Bedingung so erweitern, dass die Makrovariable ops auch eine ganze Liste von OPS-Codes enthalten darf, getrennt etwa durch Leerzeichen, und dass jedes Element der Liste am Anfang mindestens einer der 101 Variablen des Arrays gefunden werden muss (wenn das der Inhalt der "Kombinationsabfrage" sein soll):

OPS_Gesamt = 1
%do i=1 %to %sysfunc(countw(&ops,%str( )));
  & "%scan(&ops,&i,%str( ))" in: ops_ko
%end;
;

Die %DO-Schleife durchläuft alle durch Leerzeichen begrenzten "Wörter" in &ops und erzeugt für jedes "Wort", also jeden OPS-Code, eine mit UND verknüpfte Bedingung wie oben. Der UND-Operator (&) ist wegen der vorangestellten 1 (=WAHR) auch am Anfang korrekt. Das Semikolon ganz unten schließt die Zuweisung im Datastep ab. Der Code funktioniert auch mit einem einzelnen OPS-Code in &ops wie zuvor.

 

Es ist gute Praxis (um mögliche Namenskonflikte zu vermeiden), die Laufvariable i als lokal zu deklarieren, also weiter oben im Makro die Zeile

%local i;

einzufügen (oder auch gleich %local i year;).

 

Problematisch ist nur die Verwendung von &ops im Dataset-Namen tab_&ops._&icd., denn darin dürfen keine Leerzeichen vorkommen und bei langen OPS-Code-Listen könnte zudem die maximale Länge (32) von Dataset-Namen überschritten werden (auch bei Verwendung von Unterstrichen statt Leerzeichen als Trennzeichen). Ich würde die Komponente &ops. daher möglichst aus dem Namen herauslassen. Die Datasets scheinen ja sowieso nur temporär für die Auswertung mit PROC FREQ angelegt zu werden. Insbesondere werden die Datasets für 2007 bis 2015 jeweils durch das Dataset des Folgejahres überschrieben.

 

Die Makro-Aufrufe könnten dann etwa so aussehen:

%auswertung (5782 5784, M8411, 5)
%auswertung (5782 5784 5785, M8412, 5)
%auswertung (5785, M8417, 5)

 

Margaretha_97
Fluorite | Level 6

Hallo @FreelanceReinh,

vielen Dank für die ausführliche Antwort und die vielen Erklärungen sowie Verbesserungsvorschläge!

Liebe Grüße und einen schönen Abend

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
  • 2 Antworten
  • 1279 Aufrufe
  • 1 Kudo
  • 2 in Unterhaltung