Optional Drop

Hallo zusammen,

kennt jemand hier im Forum die Möglichkeit eines "optionalen Drops"?

Man nehme etwa folgenden SAS-Code:

data neu;
set alt (drop = var1);
run;

Wenn die Variable var1 nicht im Dataset alt existiert, bricht SAS ab. Gesucht ist nach einer Lösung, die eine Variable var1 dropt, wenn sie vorhanden ist und das drop-Statement quasi "überlesen" wird, wenn var1 nicht im Dataset alt vorkommt.

Ich kenne in SAS die Möglichkeit eines solchen optionalen Drops nicht, einziger Umweg wäre m.E. zuvor in einem Macro abzufragen, ob die Variable var1 in Dataset alt vorkommt.

Hat jemand dafür evtl. sogar ein geeignetes Macro zur Hand?

Bin für jeden Hinweis dankbar.

Gruß, Roman Kolbe

Ein Laufzeitvergleich ist da sicher spannend,

denn ich würde das folgendermassen ohne Makro schreiben:

data neu (drop = var1);
var1 =.;
set alt;
run;

MfG // Martin Schaefer

Laufzeitvergleich

Hallo Herr Schaefer,

im Laufzeitvergleich gewinnt Ihre Lösung sicherlich. Ich denke, dass es eine Sache der Bequemlichkeit ist.

Wenn man mehrere Variablen droppen möchte, dann muss man diese vor dem Set erzeugen und zwischen numerisch
und alphanumerisch unterscheiden, dem Makro ist das egal.

Ich habe das Makro etwas angepasst und die Laufzeiten in Abhängigkeit von Anzahl der zu droppenden Variablen
(2, 4, 6, 8 und 10) und der Anzahl der Variablen in der Datei (1000-5000 in 1000er Schritten) in eine Datei
weggeschrieben.

Die Laufzeit der Schleifen variiert von 0,2 Sekunden (2, 1000) bis ca. 4,5 Sekunden (10, 5000). Ich denke, das ist vertretbar.

Anbei noch der Code für denjenigen, den es interessiert:

%macro drop(dsn,varlist);

%local dsn varlist drop;
%let dsid=%sysfunc(open(&dsn.));
%let nvars=%sysfunc(attrn(&dsid.,nvars));
%let n = 1;
%let drop=;
%let start=%sysfunc(time());
%do %while(%scan(&varlist.,&n.) ne);
%do i = 1 %to &nvars.;
%if %upcase(%scan(&varlist.,&n.))=%upcase(%sysfunc(varname(&dsid.,&i.))) %then
%let drop=&drop. %scan(&varlist.,&n.);
%end;
%let n=%eval(&n.+1);
%end;
%let rc= %sysfunc(close(&dsid.));
%if &drop. ne %then drop=&drop.;
%let stop=%sysfunc(time());
%let dauer=%sysfunc(round(%sysevalf(&stop.-&start.),.01));
%put &start. &stop. &dauer. %eval(&n.-1) &nvars.;
%let filrf=myfile;
%let rc=%sysfunc(filename(filrf,
/appdata/sas/fb_daten/kv/H84966/a.txt));
%let fid=%sysfunc(fopen(&filrf,a));
%if &fid > 0 %then
%do;
%let rc=%sysfunc(fput(&fid,
%eval(&n.-1) &nvars. &dauer.));
%let rc=%sysfunc(fappend(&fid));
%let rc=%sysfunc(fclose(&fid));
%end;
%else
%do;

%end;

%mend drop;

Viele Grüße
Wolfgang Hornung

Makrolösung

Hallo Herr Kolbe,

mir fällt da "spontan" ein Makro ein:

%macro drop(dsn,varlist);

%local dsn varlist drop;

%let dsid=%sysfunc(open(&dsn.));
%let nvars=%sysfunc(attrn(&dsid.,nvars));
%let n = 1;
%let drop=;
%do %while(%scan(&varlist.,&n.) ne);
%do i = 1 %to &nvars.;
%if %upcase(%scan(&varlist.,&n.))=%upcase(%sysfunc(varname(&dsid.,&i.))) %then
%let drop=&drop. %scan(&varlist.,&n.);
%end;
%let n=%eval(&n.+1);
%end;
%let rc= %sysfunc(close(&dsid.));
%if &drop. ne %then drop=&drop.;
%mend drop;

options mprint;
data nein;
set sashelp.class(%drop(sashelp.class,a b c));
run;

data ja;
set sashelp.class(%drop(sashelp.class,sex age c));
run;

Vielleicht gibt es aber in den Tiefen der Optionen noch eine Möglichkeit.

Viele Grüße
Wolfgang Hornung

Warum nicht SASHELP?

Hallo Herr Hornung,

wieso lesen die die Spalten eines Datasets nicht viel einfacher aus der sashelp.vcolumn?

proc sql;
select name into :varlist
from sashelp.vcolumn
where libname=xyz
and memname=xyz
;
quit;

Gruß
Tim_Taylor

Hallo Tim_Taylor, die Lösung

Hallo Tim_Taylor,

die Lösung von Herrn Hornung funktioniert auch innerhalb eines Data-Steps und produziert nur "drop=Varlist" als Code. Ihr Beispiel würde innerhalb eines Data-Steps nicht laufen, da Sie die Prozedur SQL verwenden.

Schöne Grüße

Jan