- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
In einem Makro werden mehrere Datensätze transponiert. Als Ergebnis bekomme ich:
Datensatz 1:
_NAME_
Text
Datensatz 2:
_NAME_ COL1 COL2
Text Text Text
usw...
In einem nächsten Schritt wird eine neue Variable zugewiesen und zwar automatisch für alle Datensätze. Dies soll aber nur da geschehen wo es mehr als _NAME_ gibt, also noch min COL1 existiert oder anders gesagt, wo die Anzahl der Spalten größer als 1 ist, sonst gibt es eine Fehlermeldung. Ich dachte ich pack die in ein Array und mache ne Do Schleife von 1 bis Obs aber sobald man einen Textdreher hat, funktioniert nichts mehr.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Kleines Update, dies scheint die gewünschte Anzahl zu liefern:
proc contents data=&dataliste._1 out=&dataliste._15; run;
proc sort data=&dataliste._15; by varnum; run;
data _null_;
set &dataliste._15;
call symputx("maximum",varnum);
run;
Bekomme ich mit %PUT &maximum in den Log, also dachte ich ich prüfe ob maximum größer 1 ist.
IF &maximum > 1 THEN DO;
DATA &dataliste._17;
SET &dataliste._1;
ATTRIB VARNAMEMZPALL LENGTH=$%eval(20*&obs.);
VARNAMEMZPALL = "";
RUN;
END;
Hab ich einmal mit % vorher und einmal ohne gemacht, in beiden Fällen gibt es Fehler.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Neues Update, auch so klappt es nicht:
DATA &dataliste._17;
SET &dataliste._1;
IF &maximum > 1 THEN DO;
laenge = 2345;
ATTRIB VARNAMEMZPALL LENGTH=$%eval(20*&obs.);
VARNAMEMZPALL = "";
END;
ELSE DO;
laenge = 111;
ATTRIB VARNAMEMZPALL LENGTH=$1;
VARNAMEMZPALL = "";
END;
RUN;
laenge gibt er korrekt an, mal 2345, mal 111 aber bei der Attrib Länge meckert er obwohl der Fehler nur im 111 Fall auftreten sollte und dort anfangs gar nicht dieser Code drinnen stand.
ERROR: The length of a character variable must be in the range of 1-32767.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Zuerst die Anzahl der Variablen in eine Makrovariable stellen, und dann bedingt weitermachen:
proc sql noprint;
select count(*) into :nvar from dictionary.columns
where libname = "LIBRARY" and memname = "DATASET";
quit;
%if &nvar. gt 1
%then %do;
/* bedingter Code */
%end;
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Es gibt schon verschiedene Macros welche einem die Anzahl der Variablen zurückgeben.
Hier ein Beispiel: https://core.sasjs.io/mf__getattrn_8sas.html
Code Beispiel:
/*
* all macro compilieren
*/
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
data have;
length
_name_ $ 32
col1 8
;
_name_ = "sugus";
col1 = 123;
run;
%if %mf_getattrn(have,NVARS) > 1 %then %do;
proc print data=have;
run;
%end;
%else %do;
%put WARNING: nicht genug variablen;
%end;
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
%let dsid = %sysfunc(open(<DATASET>));
%if &dsid. > 0 %then %do;
%let varnum = %sysfunc(varnum(&dsid., <VARIABLE>));
%let dsid = %sysfunc(close(&dsid.));
%if &varnum. %then %do;
/* ... */
%end;
%end;
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Leider funktioniert das nicht so. Einiges was ihr geschrieben habt ist zu kompliziert und lässt sich nicht so einfach integrieren.
Ich versuche das ganze einen Schritt vorher zu machen, vor dem transponieren. Es werden volle und leere Datensätze transponiert und dieser Fehler erscheint nur da wo ein leerer Datensatz transponiert wurde.
Heißt ich müsste abfragen ob ich einen leeren Datensatz habe oder einen mit Inhalt, beide werden transponiert aber nur da wo auch vorher Inhalt war, entstehen Spalten und dort geht es dann weiter.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Anstatt also die Spalten zu zählen, zähle ich den Inhalt des Datensatzes vor dem transponieren.
https://www.listendata.com/2017/04/number-of-observations-in-sas-data.html
Sieht dann so aus und klappt nicht:
proc sql noprint; select count(*) into :number from &dataliste.; quit; %put &number; DATA _NULL_; SET &dataliste.; CALL SYMPUTx("anzahl",number); RUN; %IF &anzahl > 0 THEN %DO; PROC TRANSPOSE DATA=&dataliste. OUT=&dataliste._1; VAR VARNAMEMZP ; RUN; DATA &dataliste._17; SET &dataliste._1; ATTRIB VARNAMEMZPALL LENGTH=$%eval(20*&obs.); VARNAMEMZPALL = ""; RUN; %ELSE %DO; PROC TRANSPOSE DATA=&dataliste. OUT=&dataliste._1; VAR VARNAMEMZP ; RUN; DATA &dataliste._17; SET &dataliste._1; ATTRIB VARNAMEMZPALL LENGTH=$1; VARNAMEMZPALL = ""; RUN; %END;
Hab das auch ohne den Call Symput Zwischenschritt probiert, also direkt mit number verglichen. number selber wird korrekt in den Log geschrieben.
Auch mal mit und ohne % davor, mit kommen Fehlermeldungen beim kompilieren, ohne kommen Fehler beim ausführen.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
vor der Zeile
%else %do;
fehlt eine Zeile mit
%END;
Der proc sql mit select into :number hat aber nichts mit dem folgenden data _null_ step zu tun? Oder doch? Wenn ja, dann ist die Frage, was mit dem data _null_ step beabsichtigt ist.
Viele Grüße
Hans
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Vielen Dank, der Code funktioniert, komisch nur dass der andere nach dem Transpose nicht funktioniert hat.
Das Symput war dafür da um eine Variable zu generieren, geht aber auch ohne.
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Neben dem fehlenden %END fehlt das % vor THEN
%IF &anzahl > 0 THEN %DO;
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
"geht aber auch ohne" kann eigentlich nicht sein. Denn nach dem Data Step mit dem call symput wird die Macro-Variable abgefragt, die mit dem call symput erzeugt wird. Also kann es nicht ohne gehen.
Wahrscheinlich existierte die Macro-Variable von vorigen Tests in der gleichen Session.
Viele Grüße
Hans
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
Wenn klar ist, dass es mindestens eine Spalte _NAME_ gibt, dann kann's auch gleich mit dem Datastep weiter gehen:
data ds1;
length _NAME_ $10;
run;
data ds2;
set ds1;
ARRAY all _ALL_;
if dim(all)=1 then put 'WARNING: Stopping operations';
else put 'NOTE: proceeding further steps';
run;
- Cheers -
- Als neu kennzeichnen
- Lesezeichen
- Abonnieren
- Stummschalten
- RSS-Feed abonnieren
- Kennzeichnen
- Anstößigen Inhalt melden
First download a very generic macro %UT_VARLIST (ut_varlist.sas)
The macro is very useful for many other things!
Then in your macro, simply use the code:
%if %length(%ut_varlist(table=&transposed_table., exclude=_NAME_)) ne 0 %then %do; /* The transposed table variables other than _NAME_ */ %end;
%else %do;
%put WARNING: Table &transposed_table. created as a transpose of &input_table. has too few variables;
%end;