LesezeichenAbonnierenRSS-Feed abonnieren
basefan
Obsidian | Level 7

Hallo zusammen,

gibt es eine Option mit der ich dem SS beibringen kann, dass es aus einer Datei das Char-Feld 'name' sauber und korrekt einliest, obwohl es nur einen Punkt (also das Zeichen .) enthält.

Ein Beispiel:

data test;

length name $10.;

input name $ ;

LIST; /* Eingabe-Daten im Log ausgeben, hier sieht ales gut aus */

cards;

Meier

Müller

.

Schmitt

;

run; 

Ausgabe der Test-Daten: Im 3. Satz ist die Variable 'Name' komplett leer, obwohl sie mit dem Zeichen '.' gefüllt ist.

proc print data=test;

run;

Die Ausgabe mit einem data-_null_-Step hilft auch nicht weiter: Im 3. Satz ist Name immer noch leer:

data _null_;

set test;

put name=;

run;

Die Lst- bzw- Log-Ausgabe bitte selbst erzeugen.

 

Was kann ich tun, damit der Wert '.' sauber eingelesen bzw. ausgegeben wird?

Wir nutzen hier SAS 9.4 (TS1M3), Client/Server mit Windows-Clients und einem Linux-Server.

Der Effekt tritt sowohl auf dem Client als auch auf dem Server auf.

 

Viele Grüße

Hans

9 ANTWORTEN 9
mfab
Quartz | Level 8

Hallo Hans,

 

das funktioniert, indem man noch ein Informat spendiert, damit SAS weiß, was es einlesen soll:


data test;
length name $10.;
informat name char10.;
input name $ ;
LIST; /* Eingabe-Daten im Log ausgeben, hier sieht alles gut aus */
cards;
Meier
Müller
.
Schmitt
;
run; 

Viele Grüße

Michael

 

basefan
Obsidian | Level 7

Hallo Michael,

danke für die Lösung. Bisher habe ich den informat-Befehl  eher für verzichtbaren Luxus gehalten.

Ich habe es gleich ausprobiert und es klappt.

Leider klappt es nur in meinem Beispiel!

In meinem echten Code bleibt das Feld, dort heitßt es name1, unverändert leer.

 

Ich vermute es gibt einen Unterschied zwischen cards und dem echten aus einer Datei einlesen.

Ich habe meinen echten Code soweit abgespeckt, dass er überschaubar wird, aber der Effekt immer noch auftritt:

 

filename datei03 "C:\musterdaten.txt";

data test;

infile datei03 obs=999999999 LRECL=555 missover pad end=end ;

length kundnum $10 anldat_a $ 8 loevm_A $ 1 sperr $ 1 ;

length anrede $ 15 titel $ 15;

length name1 name2 name3 $ 40;

informat name1 name2 name3 char40.;

input kundnum $10. anldat_A $8. loevm_A $1. sperr $1.

anrede $15. titel $15.

name1 $40. name2 $40. name3 $40. strasse $60. plz $10. ort $40.

;

output;

run;

proc print data=test;

run;

 

Die Test-Daten sehen so aus:

004711471019990303xsFirma Name1          Name2          Strasse mit Hnr   PLZ   Ort

004711471119990202  Firma .                             Wilhelmstr. 1     54321 Musterweiler

004711471219990101  Firma Mustername AG  Spezialfabrik  Emil-Meier-Str. 1 12345 Musterort

Damit bekomme ich trotz dem informat-Befehl immer noch ein leeres Feld statt den Punkt als Befüllung.

 

Viele Grüße und vielen Dank
Hans

 

Kurt_Bremser
Super User

Das Format im input-Statement übersteuert das Format aus dem informat-Statement. Entweder an beiden Stellen das gleiche Format verwenden, oder im input gar keines, je nachdem ob formatted input notwendig ist (fixe Spalten) oder nicht.

mfab
Quartz | Level 8

Stimmt, da war ich wohl nicht ganz bei der Sache.... einfach im Input das Char-Format verwenden hätte im obigen Beispiel auch völlig ausgereicht, wenn man kein Informat verwenden will.

basefan
Obsidian | Level 7

Hallo,

ich habe weiter experimentiert und seltsamerweise hilft das informat auch mit dem cards-Befehl nichts:

 

data aaa;

length kundnum $10 anldat_a $ 8 loevm_A $ 1 sperr $ 1 ;

length anrede $ 6 ;

length name1 name2 $ 15;

informat name1 name2 char15.;

input kundnum $10. anldat_A $8. loevm_A $1. sperr $1.

anrede $6.

name1 $15. name2 $15. strasse $18. plz $6. ort $12.

;

cards;

004711471019990303xsFirma Name1          Name2          Strasse mit Hnr   PLZ   Ort

004711471119990202  Firma .                             Wilhelmstr. 1     54321 Musterweiler

004711471219990101  Firma Mustername AG  Spezialfabrik  Emil-Meier-Str. 1 12345 Musterort

;

run;

proc print data=aaa;

run;

 

Viele Grüße und vielen Dank
Hans

 

basefan
Obsidian | Level 7

Hallo Kurt,

ich war so mit experimentieren und dem erstellen des zweiten Kommentars beschäftigt, dass ich Deinen Eitrag gar nicht gesehen habe.

 

Danke für Deine Hilfe.

Jetzt klappt es auch im echten Code. Wie so oft gilt: Kaum macht man es richtig, schon funktioniert's.....

 

Danke noch einmal!

 

Viele Grüße
Hans

AndreasBachert
Calcite | Level 5

Hallo,

 

nur noch als Ergänzung:

Im Beispiel handelt es sich um eine Rohdaten-Datei, in der die unterschiedlichen Werte nicht durch ein Trennzeichen getrennt sind, sondern immer an dedizierten Spalten beginnen. In diesem Fall ist man ganz 'sauber', wenn man spaltenorientiert einliest, d.h., wenn man bei jedem Wert, den man auslesen will, angibt, an welcher Spalte er beginnt und wo er endet.

 

Der Programmcode sähe dann so aus:

 

 

data test;
   infile datei03 obs=999999999 LRECL=555 missover pad end=end ;
   length 
      kundnum     $10
      anldat_a    $8
      loevm_A     $1
      sperr       $1
      anrede      $15
      name1
      name2       $40
      strasse     $40
      plz         $5
      ort         $40
   ;
   input
      kundnum     $ 1   - 10
      anldat_A    $ 11  - 18
      loevm_A     $ 19  - 19
      sperr       $ 20  - 20
      anrede      $ 21  - 26
      name1       $ 27  - 41
      name2       $ 42  - 56
      strasse     $ 57  - 74
      plz         $ 75  - 80
      ort         $              /* Den Rest der Zeile als 'Ort' lesen */
   ;
   output;
run;
proc print data=test;
run;

 

 

Abschließende Hinweise:

  • Das Length-Statement wird nur benötigt, wenn man in der Zieltabelle andere Variablen-Längen definieren will, als sie in der Rohdatendatei vorgesehen sind
    • Wenn man z.B. das Length-Statement für name2 weglässt, würde die Variable mit einer Länge von 15 in der Zieltabelle deklariert (da man ja der Variablen die Zeichen aus den Spalten 42 - 56 zuweisen lässt)
  • Ein Informat benötigt man, wenn man z.B. einen Text einlesen will, der ein Datum bedeutet. Dann muss man SAS 'sagen', wie die betrffenden Zeichen zu übernemen sind.
    •  z.B. muss der Text 12NOV2016 mit dem Informat DATE9. eingelesen werden, damit der Text in der Zieltabelle zu einem Datumswert wird
  • Wenn man, wie im Code-Beispiel zu sehen, bei jedem Wert angibt, wo er beginnt und wo er endet, kann man auch Werte einfach überspringen, wenn man sie nicht in der Zieltabelle benötigt
    • Wenn man z.B. den Wert für loevm_A ncht benötigt, lässt man loevm_A einfach aus dem Input-Statement weg und der Code funktioniert immer noch
    • Dann wird einfach das Zeichen, das in der Spalte 19 der Rohdatenzeile steht, einfach nirgendwo verwendet

Viele Grüße

Andreas

Patrick
Opal | Level 21

Ein einzelner Punkt ist ein Spezialfall und steht in einem SAS Kontext oftmals fuer Missing Value.

$CHAR. ist ein Informat welches Punkte nicht zu blanks konvertiert.

 

Mit dem LIST command wird der Input Buffer in den Log rausgeschrieben. Der Punkt wird erst konvertiert, wenn man eine Variable gegen diesen Input Buffer "mapt". 

 

http://support.sas.com/documentation/cdl/en/leforinforref/64790/HTML/default/viewer.htm#n06dgsx9u83o...

 

Details

The $w. informat trims leading blanks and left aligns the values before storing the text. In addition, if a field contains only blanks and a single period, $w. converts the period to a blank because it interprets the period as a missing value. The $w. informat treats two or more periods in a field as character data.

Comparisons

The $w. informat is almost identical to the $CHARw. informat. However, $CHARw. does not trim leading blanks nor does it convert a single period in an input field to a blank, while $w. does both.

 

data test;
  infile datalines dlm=' ' truncover;
  input name :$char10.;
  cards;
Meier
Müller
.
Schmitt
;
run;

 

basefan
Obsidian | Level 7

Hallo zusammen,

@Andreas

Danke für die Info, aber ich bleibe erst mal bei unserer bisherigen Vorgehensweise. Die erscheint mit Änderungsfreundlicher zu sein.

 

@Patrick

Danke für die Details zum char-Format. Damit ist das 'seltsame' Verhalten geklärt. Dank dem Link bin ich noch auf eine Gemeinheit bei der Verwendung vom char-Format gestoßen:

If you use $CHARw. in an INFORMAT or ATTRIB statement within a DATA step to read list input, then by default SAS interprets any blank embedded within data as a field delimiter, including leading blanks.

Zum Glück habe ich aus Gewohnheit kein informat verwendet .... !

 

Viele Grüße
Hans

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

Diskussionsstatistiken
  • 9 Antworten
  • 3197 Aufrufe
  • 6 Kudos
  • 5 in Unterhaltung