viele ähnliche Datensätze automatisch einlesen

Hallo community,

ich suche nach einer Methode, wie ich am effektivsten ca. hundert Datensätze (.csv-Dateien) im Data Step einlesen kann, die jeweils mehrere hundert Variablen enthalten. Die verschiedenen Datensätze haben teilweise die gleichen Variablen, es gibt aber einige Variablen, die nicht in allen Datensätzen vorkommen. Das input-statement muss also variabel gestaltet werden. Dazu fällt mir folgendes ein:
1. Tabelle erstellen, die ALLE Variablen sowie deren Formate enthält
2. Makro zum Einlesen der hundert Datensätze:
- erste Zeile eines Datensatzes lesen, diese enthält die Variablennamen
- mit Hilfe der Formate-Tabelle das input-statment in einer Makro-Schleife zusammenbasteln
Dies ist erst mal eine vage Idee, die mir etwas kompliziert vorkommt. Bin ich auf dem richtigen Weg? Weiß jemand eine bessere Methode? Ich vermute, dass das Problem relativ häufig auftritt.

Viele Grüße,
Barbara Sarholz

interessantes Problem

Das ist ein interessantes Problem. Eine vorgefertigte Lösung ist mir nicht bekannt. Folgende Lösung sollte funktionieren. Ich habe es nicht als Makro implementiert, es sollte aber sehr leicht dahin erweiterbar sein.

/* Beispieldatei erzeugen mit Daten in unterschiedlichen Formaten */
data _null_;
   
file 'c:\temp\daten.csv';
   
put 'x;y;c';
   
put '1,1;1.1;AA';
   
put '2,2;2.2;BBB';
   
put '3,3;3.3;CCCC';
run;

/* Datei mit Formaten (und den richtigen Informaten!) erzeugen */
data formate;
   
attrib
      
x length=8  format=commax10.2 informat=numx. label='variable x'
      
y length=8  format=commax10.2 informat=best. label='variable y'
      
z length=8  format=commax10.2 informat=numx. label='variable z'
      
c length=$8 format=$8.        informat=$8.   label='variable c'
      
;
run;

/* die Namen der Variablen ermitteln */
data _null_;
   
infile 'c:\temp\daten.csv' lrecl=32767 recfm=v truncover;
   
input names $32767.;
   
call symput('names',trim(translate(names,' ',';')));
   
stop;
run;

/* und jetzt die eigentlichen Daten lesen */
data daten(keep=&names);
   
/* Variablenattribute holen */
   
if _n_=1 then set formate;
   
infile 'c:\temp\daten.csv' dsd dlm=';' lrecl=32767 recfm=v truncover;
   
if _n_=1 then input; /* Namen überlesen */
   
input &names;
run;

schöne Lösung!

Hallo Herr Mangold,

vielen Dank! So lässt sich mein Problem einfacher lösen als erwartet... Ich werde es gleich mal an meinen realen Daten ausprobieren.

Beste Grüße,
Barbara Sarholz

viele Dateien einlesen

Hallo,
die Aufgabe "viele Dateien einlesen" geht auch so zu lösen:

%let MyPath=C:/irgend_ein_Pfad;
%let MyWork=DatenLib;
%file2ds( infile=&
.MyPath/daten1.csv
        , outfile=&
MyWork..DataSet_von_daten1
        );
%file2ds( infile=&
.MyPath/daten2.csv
        , outfile=&
MyWork..DataSet_von_daten2
        );
%file2ds( infile=&
.MyPath/daten3.csv
        , outfile=&
MyWork..DataSet_von_daten3
        );
u.s.w so oft wie nötig, ggf. als Macro-Schleife: Über alle csv-Dateien im Verzeichnis (Ordner) C:/irgend_ein_Pfad.
Die Macro-Definition zu file2ds findet sich in der
Redscope Makro-Sammlung unter "meinen" Macros (also unter org.redscope.HansKneilmann.*) dort der Eintrag/Macro org.redscope.HansKneilmann.file2ds. Im file2ds wird der Macro obsnvars verwendet, der steht auch zum download an gleicher Stelle unter org.redscope.HansKneilmann.obsnvars.
Die file2ds-Lösung hat den Vorteil, dass alles variabel ist, man braucht nichts über den Input zu wissen (z.B. Anzahl Spalten oder Namen der Spalten/Variablen), sie hat den Nachteil, dass alles über einen Kamm geschoren wird! Das heißt alle Variablen sind char 200 (oder lt. Macro-Parameter laenge). Ggf. sollte man dann im data-Befehl die compress=YES-Option verwenden.
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

P.S.: Ich meine mich erinnern zu können, dass das Kernstück von dem file2ds-Macro von irgendwoher abgeschrieben ist ...
Aber ich finde keine Notizen mehr woher abgeschrieben ...

nächster Schritt

Hallo Herr Kneilmann,

danke für den Hinweis. Sie kommen mit Ihrer Antwort schon auf mein nächstes Problem zu sprechen: Wie kann man denn alle Dateien eines Ordners für den Import ansprechen?

Gruß,
Barbara Sarholz

Suchen ....

Hallo,
ich meine mich zu erinnern, dass auch dazu eine Lösung hier in Redscope diskutuert bzw. vorgesteelt wurde ....
Bitte selber suchen ;-)
Die Vorgehensweise ist immer gleich:
Mit dem SAS-Base-X-Befehl einen Betriebssystem-Befehl absetzen: Liste aller Dateien im Ordner Y erzeugen,
diese Liste nach SAS-Base einlesen. Das erfolgt entweder über die pipe oder über "Liste in Text-Datei ausgeben lassen und diese dann einlesen (und dann löschen).
et voila: Die Liste der Datei-Namen ist da ...
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Finden...

Leider ist es of schwierig, etwas zu finden, wenn man nicht genau weiss, wonach man suchen soll. Aber danke für den Tipp mit dem X-Befehl :-)
Für alle, die auf dieser Seite ebenfalls nicht fündig geworden sind ein Link, der zumindest mir weitergeholfen hat:
http://www.tau.ac.il/cc/pages/docs/sas8/unixc/xcomm.htm

SAS auf UNIX

Hallo Frau Sarholz,
sehe ich das richtig dass der Link in der UNIX-'Ecke' geht?
Könnte es also sein, dass sie mit SAS auf einer UNIX-Maschine arbeiten????
Wenn ja, dann ist alles ganz einfach, zum Beispiel so

%macro doit;
  
%let fullpath=/u1/IN3/bla_Ordnder;

  
/* Liste (filelist) der xyz-Dateien für EINEN Tag */
  
/* Datei-Name (UNIX-gemäß) generisch angegeben    */
  
X "ls -1 &fullpath./dwh.son.adre.01.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] > _ls_tmp_adreinle3.txt 2>/dev/null"; /* Fehler-Umlenkung nach dev null wg. 'No such file or directory' */
  
filename tmpfile '_ls_tmp_adreinle3.txt';
  
%put INFO: sysfilrc=&sysfilrc.;
  
%if &sysfilrc. eq 0        /* Wenn Datei vorhanden genauer:  */
                             
/* Wenn flat file vorhanden       */
  
%then %do;
    data filelist;
      infile tmpfile lrecl=
120 missover pad;
      length bigline $
120;
      input  bigline
$120.;
    run;
    filename tmpfile ;            
/* reset file ref   */
    
X 'rm _ls_tmp_adreinle3.txt'; /* lösche flat file */

    
proc print data=filelist;       /* bigline ausgeben */
    
run;
  
%end;
%mend doit;
%doit;
Danach sind die Dateinamen als SAS Data Set vorhanden und verarbeitbar, viel Spaß ...
Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

P.S. (Nachtrag, 28.02.2008):
Ausserdem gibt es noch in der S A S S A M P L E L I B R A R Y ein schönes Beispiel (die Sample Library ist zu finden unter: SAS->Help->Sample Programms->SAS/Connect->Upload SAS Source Programs to Remote Session). Den Code habe ich als macro UPLDPROG in "meine" Macro-Sammlung Macro-Sammlung als "org.redscope.HansKneilmann.filelist" eingefügt.

geschafft!

Hallo Herr Kneilmann,

danke für den Code. Ich habe es inzwischen auch irgendwie hinbekommen, allerdings nicht so schön mit Fehlerumlenkung/auffangung wie Ihre Variante. Ich werde das noch in mein Programm integrieren :-)
Schöne Grüße,
Barbara Sarholz

Benutzerkonto: email-Adr. für (direkt) Kontakt, Firmen-Infos ..

Hallo Frau Sarholz,
eine Bitte an Sie und an die Forumsmitglieder, insbesondere die neuen Mitglieder

Die meisten (oder jedenfalls sehr viele) Mitglieder haben in ihren Kontaktdaten keine email-Adresse hinterlegt. Das finde ich schade, denn oft ist es hilfreich, auch über email zu kommunizieren.

Diese Bitte ist eine Kopie aus dem Forums-Beitrag Eine Bitte an alle (neuen) Forumsmitglieder zum Thema "email-Adresse hinterlegen" und zum Thema "Infos über die eigene Firma".

Natürlich sind Infos unter "Interesse an SAS-Software" auch sehr interessant, dort kann man/frau z.B. ein paar Worte über die Hard- und Software-Umgebung verlieren, in der das liebe SAS läuft. Also z.B. (Fat-)Client-/Server mit Windows/Unix oder (Thin-)Client-/Server mit X-Windows auf'm PC und SAS auf Unix-Server oder ...

Mit neugierigen Grüßen aus dem trüben Westerwald
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Pipe

Folgendes liest bei mir unter Windows XP Pro Deutsch ein Verzeichnis in eine SAS-Datei ein, unter Unix muss man sicher ein paar Modifikationen vornehmen:

filename dir pipe 'dir c:\temp';
data dateien (drop=datum char);
   
infile dir truncover ;
   
input char $1. @;
   
if char ne ' ' then do;
      
input
         
@1  datum   ddmmyy10.
         
@13 zeit    time5.
         
@22 dir     $5.
         
@28 groesse commax8.
         
@37 name    $40.
      
;
      zeit = dhms(datum,hour(zeit),minute(zeit),second(zeit));
      
output;
   
end;
   
format zeit datetime.;
run;