Datensatz mit vielen Spalten einlesen --> wie automatisieren?

Hallo zusammen!

Ich bin eine SAS-Anfängerin und habe ein für SAS-erfahrene User wohl leicht zu lösendes Problem (hoffentlich). :o)

Ich möchte einen Datensatz mit ca. 54 000 Spalten in SAS einlesen. Der Datensatz liegt im csv-Format vor. Das Einlesen funktioniert soweit, aber ich weiss nicht so genau, wie ich beim Input-Statement mit den vielen Spalten vorgehen soll. Mein Data-Schritt sieht bis jetzt so aus:

data typ;
infile 'C:\Daten\datei.csv' DLM=';';
length Nr$ 15;
input Nr $ # Nr ist nicht fortlaufend
xyz1 $ # xyz-Spalten können fortlaufend nummeriert sein (1 - ca. 54 000)
xyz2 $
xyz3 $
xyz4 $;
run;

Wie kann man es Automatisieren, dass die Spalten alle eingelesen werden, ohne dass ich jetzt 54 000 Mal xyzXXX hinschreiben muss? Die Beschriftung für diese Spalten soll entweder fortlaufend nummeriert sein oder aus einer anderen Datei übernommen werden. Bin mir sicher, dass das Problem relativ leicht zu lösen ist. Aber ich habe weder hier im Forum noch sonst irgendwo eine Lösung für mein Problem gefunden.

Vielen Dank schonmal im Voraus!

Viele Grüße,
Melanie

Einlesen mit DO-Schleife

Hallo Melanie,
die Lösung ist einfacher als ich zuerst dachte.
Zuerst spielte ich mit dem Gedanken an eine Macro-Lösung. Die hat aber den Nachteil, dass alle 54.000 Input-Variablen im LOG ausgegeben werden (wenn man MPRINT einschaltet, was sehr zu empfehlen ist).
Also habe ich die Idee mit der SAS-Base-do-Schleife weiter verfolgt.
Ich habe natürlich nur mit 99 Feldern getestet statt 54.000 Feldern.
Hier das Ergebnis:

data typ;
infile 'C:\tmp\test_datei.csv'
delimiter= ';'
LRECL=999 /* default ist zu kurz !!! */
missover /* "zu kurze" Sätze (Feld fehlt komplett) mit 'missover' kein Problem */
pad /* Sätze mit "halben Feldern" dank 'pad' kein Problem */
DSD /* DSD=EIN!!! Grund: Doppel-Delimiter als leeres Feld behandeln */
;
length Nr $10;
array xyz_A $10 xyz1-xyz99; /* Test mit max. 99 Feldern statt 54.000 */

input Nr $ @ ; /* Satz für nächsten INPUT-Befehl halten */

drop ii; /* Schleifenzähler NICHT ausgeben */
do ii=1 to dim(xyz_A);

input xyz_A(ii) $ @ ; /* Feld ii einlesen, Satz für nächsten INPUT-Befehl halten */

end;
run;

proc print data=typ(obs=3);
run;

Getestet habe ich es mit einer Datei mit 78 Variablen und 7 Sätzen.
Viel Spaß damit!

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Hallo! Das funktioniert

Hallo!

Das funktioniert wunderbar! Super! Dachte mir, dass das mit einer DO-Schleife funktioniert, wusste nur leider nicht genau, wie. :o)

Habe das jetzt gleich bei einer weiteren (ähnlichen) Datei probiert. Hier taucht aber gleich die nächste Frage auf. Die erste Zeile möchte ich hier gerne als Spaltenüberschrift übernehmen. Bei PROC IMPORT geht das ja über getnames=yes. Wie funktioniert das beim Einlesen mit einem DATA-Schritt?
Kann die Datei leider nicht mit Hilfe des Import Wizard importieren, da ich auf einem UNIX-Rechner arbeite.

Viele Grüße,
Melanie

UNIX-Rechner ...

ist sowieso gut!!! :-))))

Im infile-Befehl einfach firstobs=2, dann wird die erste Zeiel überlesen.

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Dankeschön! :o)

Geht es auch, dass die erste Zeile als Spaltenbeschriftung übernommen wird? Dann wären (vorerst) alle meine Fragen / Probleme geklärt! :o)

Viele Grüße,
Melanie

Macro file2ds

Hallo Melanie,
wenn die erste Zeile als Spalten-Beschriftung übernommen werden soll, dann ist es noch einfacher als mit der Lösung mit den 54.000 Feldern und der DO-Schleife vom 17. Aug.2010, 09:39: Man/frau nehme den Macro file2ds.

Der befindet sich in der Redscope-Makro-Sammlung unter org.redscope.HansKneilmann.*

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Dankeschön!

Vielen Dank für die schnelle Hilfe! Das scheint die Lösung meines Problems zu sein (muss mich nur zuerst mal in die Makro-Programmierung einarbeiten). :o)

Viele Grüße,
Melanie

Klappt einfach so

Hallo Melanie,
der Macro klappt einfach so. Das muss mich nur zuerst mal in die Makro-Programmierung einarbeiten ist dazu nicht nötig!
Einfach die Macro-Definition vor dem Benutzen per submit oder rsubmit wegschicken, z.B. als Teil der autoexec.sas und schon kann man/frau ihn benutzen, einfach so!

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Option DSD

Hallo Herr Kneilmann,

danke für den Tipp mit der Option DSD, die habe ich schon gesucht.

Als Anregung: Wenn man nicht genau weiß, wieviele Spalten einzulesen sind, könnte man in der ersten Zeile die Delimiter zählen und damit die Dimension des Arrays festlegen.

Grüße
SteffenM

Option DSD mit Risiken und Nebenwirkungen

Hallo Steffen,
die Option DSD ist zwar schön, aber sie hat auch Nebenwirkungen (zu denen der Arzt oder Apotheker nichts sagen kann .... aber dafür gibt es dieses Forum!)

Wenn mit DSD, dann ist ein Mehrfach-Delimiter KEIN Problem (Stichwort: Doppel-Semikolon)
             Bsp. vkorg;vtweg;;;Name1;Name2 wird zu vkorg=vkorg vtweg=vtweg etc pp
             Bsp. _N_=1: vkorg;vtweg;X;Y;Name1;Name2
                  _N_=2: 1010 ; 10  ;;;  Name1;Name2
                  wird zu vkorg=1010 vtweg=10, X=leer, Y=leer, Name1=Name1, Name2=Name2
             aber die Gänsefüßchen sind EIN Problem
             Bsp. "Name1;Name2" wird zu Name1=Name1;Name2 und Name2=leer !!!
Wenn ohne DSD, dann ist Gänsefüßchen (Double-Quote, Single-Quote) KEIN Problem
             Bsp. "Name1;Name2" wird zu Name1="Name1 und Name2=Name2")
             aber die Mehrfach-Delimiter sind EIN Problem
             Bsp. _N_=1: vkorg;vtweg;X;Y;Name1;Name2
                  _N_=2: 1010 ; 10  ;;;  Name1;Name2
                  wird zu vkorg=1010 vtweg=10, X=Name1, Y=Name2, Name1=leer, Name2=leer

Und sage bitte keiner solche Fälle kommen nicht vor ... das sind alles Beispiele aus der Praxis!

Zur Info: DSD meint delimiter-sensitive data

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)