LesezeichenAbonnierenRSS-Feed abonnieren
Fay123
Obsidian | Level 7

Hallo zusammen,

 

ich habe folgende Tabelle aus der ich einen bestimmten Datensatz herausfiltern muss:

 

SAS.png

 

In der 2. Spalte springt ein Fall ggf. von A nach B oder C, N ... Die Daten sind nach Kundennummer und Datum aufsteigend sortiert. Bei dem angegebenen Kunden bräuchte ich in diesem Fall aus Spalte 2 die aktuelle Bewertung (=B) und aus der Datumsspalte, wann der Kunde zum letzten Mal in diese Bewertung gefallen ist (=9.Sep. 2015)

 

Langsam verzweifle ich, vielleicht kann jemand helfen (im DI Studio oder Enterprise Guide)?

Vielen Dank!

14 ANTWORTEN 14
Kurt_Bremser
Super User

Bitte, bitte, Daten nicht als Bilder posten.

Wenn ich da was testen will, muss ich alles aus dem Bild abtippen.

Bitte lieber gleich einen Data Step mit datalines in ein Code-Window posten.

 

Dieses gesagt:

data want;
set have;
by customer;
retain change_date;
lastbew = lag(bewertung);
if first.customer
then change_date = .;
else
  if bewertung = 'B' and lastbew ne 'B'
  then change_date = date;
format change_date datetime19.;
if last.customer then output;
run;
Fay123
Obsidian | Level 7
Vielen Dank und Entschuldigung !
CKothenschulte
Obsidian | Level 7

Hallo Fay123,

 

Testdaten in kopierbarer Form wären nett Smiley (zwinkernd)

 

Anbei meine Lösung mit dem beliebten "IF first. und last." und "Retain".

 

data EINGABE;
input KUNDENNUMMER BEWERTUNG $ DATUM;
attrib DATUM format=DDMMYYP10.;
cards;
1 A 19999
1 B 20000
1 A 20001
1 A 20002
1 B 20003
1 B 20004
2 A 19999
2 B 20000
2 A 20001
2 A 20002
2 B 20003
2 A 20004
;;;;
run;

proc sort data=EINGABE;
  by KUNDENNUMMER DATUM;
run;

data ERGEBNIS (drop=DATUM_R BEWERTUNG_R);
  set EINGABE;
  by KUNDENNUMMER;
  retain BEWERTUNG_R;
  retain DATUM_R;
  if first.KUNDENNUMMER then do;
    BEWERTUNG_R = Bewertung;
	DATUM_R = DATUM;
  end;

  if BEWERTUNG_R ne BEWERTUNG then do;
    BEWERTUNG_R = Bewertung;
    DATUM_R = DATUM;
  end;

  if last.KUNDENNUMMER then do;
    DATUM = DATUM_R;
	output;
  end;
run;
Fay123
Obsidian | Level 7
Danke sehr! 🙂
Fay123
Obsidian | Level 7

Jetzt muss ich bei meinem Datensatz noch einmal nachfragen. Herauskommen sollen Bewertung und Datum der letzten Änderung, aktuell also bei mir: Bewertung B und Datum 9.9.2015. Heraus kommt bei dem Programm allerdings A und der 30.05.2012.

 

Kundennummer Bewertung Datum

1022-01 A 300512
1022-01 B 130612

1022-01 A 200815
1022-01 A 030915
1022-01 B 090915
1022-01 B 031215
1022-01 B 160316
1022-01 B 170616
1022-01 B 090916
1022-01 B 081216
1022-01 B 090317
1022-01 B 210617
1022-01 B 150917
1022-01 B 121217

 

Merci

CKothenschulte
Obsidian | Level 7

Passt eventuell was mit der Datenstrukur nicht?

Ich habe mein Testdatenprogramm (nur den ersten Data-Step!) angepasst, damit die Kundenummer alphanumerisch ist und das Datum richtig interpretiert wird.

 

data EINGABE (drop=DATUMC);
input KUNDENNUMMER $ BEWERTUNG $ DATUMC $;
datum = mdy(input(substr(DATUMC,3,2),2.), input(substr(DATUMC,1,2),2.), 2000 + input(substr(DATUMC,5,2),2.));
attrib DATUM format=DDMMYYP10.;
cards;
1022-01 A 300512
1022-01 B 130612
1022-01 A 200815
1022-01 A 030915
1022-01 B 090915
1022-01 B 031215
1022-01 B 160316
1022-01 B 170616
1022-01 B 090916
1022-01 B 081216
1022-01 B 090317
1022-01 B 210617
1022-01 B 150917
1022-01 B 121217
;;;;
run;

proc sort data=EINGABE;
  by KUNDENNUMMER DATUM;
run;

data ERGEBNIS (drop=DATUM_R BEWERTUNG_R);
  set EINGABE;
  by KUNDENNUMMER;
  retain BEWERTUNG_R;
  retain DATUM_R;
  if first.KUNDENNUMMER then do;
    BEWERTUNG_R = Bewertung;
	DATUM_R = DATUM;
  end;

  if BEWERTUNG_R ne BEWERTUNG then do;
    BEWERTUNG_R = Bewertung;
    DATUM_R = DATUM;
  end;

  if last.KUNDENNUMMER then do;
    DATUM = DATUM_R;
	output;
  end;
run;

Anschließend bekomme ich das korrekt Ergebnis:

KUNDENNUMMER BEWERTUNG datum
1022-01 B 09.09.2015

andreas_lds
Jade | Level 19

Eigentlich muss der Vorschlag von @Kurt_Bremser nur etwas angepasst werden - ich verzichte auf die lag-Funktion. Muss noch mit mehreren Kundennummern getestet werden.

 

data work.Eingabe;
   attrib
      Kundennummer length= $ 7
      Bewertung length= $ 1
      Datum length= 8 format=ddmmyyp10. informat=ddmmyy.
   ;

   input Kundennummer Bewertung Datum;

   datalines;
1022-01 A 300512
1022-01 B 130612
1022-01 A 200815
1022-01 A 030915
1022-01 B 090915
1022-01 B 031215
1022-01 B 160316
1022-01 B 170616
1022-01 B 090916
1022-01 B 081216
1022-01 B 090317
1022-01 B 210617
1022-01 B 150917
1022-01 B 121217
;
run;


data work.Ziel;
   set work.Eingabe;
   by Kundennummer;

   length LetzteBewertung $ 1 LetzteAenderung 8;
   retain Letzte:;
   format LetzteAenderung ddmmyyp10.;

   if first.Kundennummer then do;
      call missing(of Letzte:);
   end;

   if Bewertung ^= LetzteBewertung then do;
      LetzteBewertung = Bewertung;
      LetzteAenderung = Datum;
   end;

   if last.Kundennummer then output;

   keep Kundennummer Letzte:;
run;
HeideTribius
Fluorite | Level 6

hallo,

 

mit lag():

 


data daten;
        input Kundennummer $ Bewertung $ Datumt $;
        cards;
1022-01 A 300512
1022-01 B 130612
1022-01 A 200815
1022-01 A 030915
1022-01 B 090915
1022-01 B 031215
1022-01 B 160316
1022-01 B 170616
1022-01 B 090916
1022-01 B 081216
1022-01 B 090317
1022-01 B 210617
1022-01 B 150917
1022-01 B 121217
;
run;
 
data ergebnis(keep=kundennummer bew dat);
retain bew dat;
        set daten;
        datum = input(datumt,ddmmyy6.);
        by kundennummer;
        if lag(bewertung) ne bewertung then do;
                bew = Bewertung;
                dat = datum;
        end;
        if first.kundennummer then do;
                bew = Bewertung;
                dat = datum;
        end;
        if last.kundennummer then output;
        format dat eurdfdd10.;
run;

viele Grüße. Heide

 

Fay123
Obsidian | Level 7

Vielen Dank an alle! Frau (fröhlich)

basefan
Obsidian | Level 7

Hallo zusammen,

der letzte Lösungsvorschlag liefert nicht das Datum vom letzten Wechsel nach B sondern das Datum vom letzten Wechsel (egal wohin).

Mit geänderten Test-Daten sieht man den Fehler schnell:

Der Code

data daten;

input Kundennummer $ Bewertung $ Datumt $;

cards;

 

1022-01 A 300512

1022-01 B 130612

1022-01 A 200815

1022-01 A 030915

1022-01 B 090915

1022-01 B 031215

1022-01 B 160316

1022-01 B 170616

1022-01 B 090916

1022-01 B 081216

1022-01 A 090317

1022-01 A 210617

1022-01 A 150917

1022-01 A 121217

;

run;

data ergebnis(keep=kundennummer bew dat);

retain bew dat;

set daten;

datum = input(datumt,ddmmyy6.);

by kundennummer;

if lag(bewertung) ne bewertung then do;

 

bew = Bewertung;

dat = datum;

end;

if first.kundennummer then do;

 

bew = Bewertung;

dat = datum;

end;

if last.kundennummer then output;

format dat eurdfdd10.;

run;

 

liefert

Obs bew dat Kundennummer

1 A 09.03.2017 1022-01

 

Die Lösung von Kurt liefert auch mit diesen Daten das korrekte Datum

09.09.2015

Verwirrend ist, dass sie nicht die dazu passende Bewertung liefert, das war aber auch nicht gefordert.

 

Viele Grüße

Hans

 

Nachtrag: Alle Lösungen, außer die von Kurt, liefern mit den geänderten Test-Daten nicht das korrekte Datum 09.09.2015 sondern.

HeideTribius
Fluorite | Level 6
hallo Basefan,

lt. Aufgabenstellung sollte die "aktuelle Bewertung ... und aus der Datumsspalte, wann der Kunde zum letzten Mal in diese Bewertung gefallen ist " ermittelt werden.
Das klingt erst einmal nicht so, als sollte gezielt nach "Bewertung B" gesucht werden?
Andernfalls müsste in beiden Abfragen ("if lag(Bewertung)..." und "if first.kundennummer") die Zusatzbedinung "and Bewertung = "B"" untergebracht werden.

viele Grüße. Heide
basefan
Obsidian | Level 7

Hallo Heide,

stimmt!

Ich hatte den Satz 'Bei dem angegebenen Kunden bräuchte ich in diesem Fall aus Spalte 2 die aktuelle Bewertung (=B) und aus der Datumsspalte, wann der Kunde zum letzten Mal in diese Bewertung gefallen ist (=9.Sep. 2015)' falsch verstanden. Ich hatte verstanden, dass es um den Wechsel nach B ginge.

Also sind Eure Lösungen korrekt und die von Kurt geht offensichtlich auch vom gleichen falschen Verständnis der Aufgabenstellung aus.

Sorry für die angerichtete Verwirrung.

 

Viele Grüße

Hans

Fay123
Obsidian | Level 7

Nichtsdestotrotz habt ihr mir alle sehr geholfen. Danke nochmals dafür!

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
  • 14 Antworten
  • 3407 Aufrufe
  • 25 Kudos
  • 6 in Unterhaltung