Beobachtungen Zählen mit Hilfe von Schleifen?

Hallo zusammen,

ich habe folgendes Problem, ich möchte Kunden zählen, die innerhalb der letzten 12 Monate bestellt haben. Das ganze würde ich gerne auf Monatsebene für die letzten 20 Jahre haben.

Also x Kunden haben vom 01.01.2009 - 01.01.2010 gekauft,und x vom 01.02.2009 - 01.02.2010 etc.
auch wenn ein Kunde öfter in dem einem Jahr gekauft hat, soll er nur einmal enthalten sein.

Dazu habe ich eine Tabelle mit allen Kunden und den Kaufdaten, das ich inzwischen als YYYYMM ungewandelt habe.

Kunde Datum
1 199907
2 200912
3 201005 etc.

Ich dachte an eine Schleife, die die Kunden zählt, die innerhalb von dem entsprechenden Datum dann
+100 bestellt haben (also vom 200805 bis 200905) die Tabelle dann also nach Datum sortiert.

und eine zweite Schleife, die dann immer jeweils einen Monat weiter geht.
Aber ich komme irgendwie nicht weiter.

Über Hilfe würde ich mich riesig freuen.
Viele Grüße
Gabriele

RE: Beobachtungen Zählen mit Hilfe von Schleifen?

Hallo Gabriele.

Ich würde das Thema mit einem Makro erschlagen. Zunächst einmal die Grundidee:

data bestelldaten;
input Kunde Datum;
datalines;
1 199907
2 200912
3 201005
1 199912
2 200908
5 201004
4 201005
2 200001
;

%let startdatum = 199905;

proc sql;
create table nachmonat as
select
input(compress("&startdatum"||"01"), yymmdd8.) as StartDt format = ddmmyyp10.
, intnx('month', input(compress("&startdatum"||"01"), yymmdd8.), 12) as EndDt format = ddmmyyp10.
, count(distinct Kunde) as kaeufer
from bestelldaten
where
calculated StartDt <=
input(compress(put(Datum, 6.)||"01"), yymmdd8.) <=
calculated EndDt
;
quit;

Das PROC SQL zählt die Kunden (einfach) im Zeitraum eines Jahres und das monatsbasiert. Dazu greife ich auf die Datumsfunktion INTNX zurück, die einen Datumswert um ein bestimmtes Intervall verschiebt. Liegen Deine Datumswerte in den Originaldaten in einem anderen Format als YYYYMM vor, ließe sich der Code hier noch vereinfachen. Ich bin von den Daten wie oben im Datensatz "bestelldaten" angegeben vorliegend ausgegangen.

Nun muss mit einem Makro eine Schleife erzeugt werden, die das PROC SQL für jeden gewünschten Jahreszeitraum ausgehend von einem Startmonat ausführt. Die Ergebnisse habe ich in einer Gesamtdatei zusammengeführt:

%macro customer_by_month(from, to, outdsn = work.result);
/**
FROM: Startmonat für das erste Auswertungsjahr im Format YYYYMM.
TO: Startmonat für das letzte Auswertungsjahr im Format YYYYMM.
**/

/** Erstelle Dataset mit allen Startmonaten in der angegebenen Sequenz **/
data dateseq;
nextmonth = "&from";
output;
do while(nextmonth < &to);
nextmonth = put(intnx('month', input(compress(put(nextmonth, 6.)||"01"), yymmdd8.), 1), yymmn6.);
output;
end;
run;

/** Makrovariable je Startmonat erstellen **/
data _null_;
set dateseq end = fin;
call symput(compress("m"||_n_), nextmonth);
if fin then call symput('nn', _n_); /*<==Anzahl der Datensaetze fuer die DO-Schleife **/
run;

/** Schleife je Auswertungsjahr **/
%let setstring = ;
%do cc = 1 %to &nn;
proc sql;
create table auswertung&cc as
select
/** Startmonat als Datumswert **/
input(compress("&&m&cc"||"01"), yymmdd8.) as StartDt format = ddmmyyp10.
/** Aktueller Startmonat als Datumswert (auf den Monatsersten gesetzt) **/
, intnx('month', input(compress("&&m&cc"||"01"), yymmdd8.), 12) as EndDt format = ddmmyyp10.
/** Anzahl der Kunden ohne Wiederholungen gezaehlt **/
, count(distinct Kunde) as kaeufer
from bestelldaten
where
calculated StartDt <=
input(compress(put(Datum, 6.)||"01"), yymmdd8.) <=
calculated EndDt
;
quit;
%let setstring = &setstring auswertung&cc;
%end;

/** Alle Monatsauswertungen in einen Ergebnisdatensatz schreiben **/
data &outdsn;
set &setstring;
where StartDt ne . and EndDt ne .;/** Loeschen der Datensaetze (Jahre) ohne Kaeufe **/
run;

/** Aufraeumen **/
proc datasets library = work nodetails nolist;
delete &setstring dataseq;
quit;

%mend customer_by_month;

Aufrufbar mit (Beispiel):

%customer_by_month(199901, 201005)

Wie gesagt, wenn die Datumswerte im Original anders vorliegen (z.B. als SAS Datum), dann lässt sich der Code noch etwas vereinfachen.

Ich hoffe, damit in etwa das getroffen zu haben, was Du brauchst.

Viel Spass

D. Dolic

Super, vielen lieben Dank,

Super,
vielen lieben Dank, das klingt nach genau dem, was ich suche, da werde ich mich gleich mal ransetzen.

Die Datumswerte liegen als YYYYMMDD vor, ich hatte nur gedacht, ich vereinfache das, wenn ich die in der oben angegebenen Form habe, da mich ja nur die Monateebene interessiert.

Viele Grüße
Gabriele