LesezeichenAbonnierenRSS-Feed abonnieren
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Dvdscot
Obsidian | Level 7

Hallo,

 

ich hab mehrere große Datensätze, damit ich die einfach kombinieren kann, will ich in beide Indikatoren einbauen. Ursprünglich hab ich einen Datensatz aufgeteilt und transponiert.

 

In dem ersten müsste die Zahlenfolge 1 bis 16 so lange rein bis es nicht mehr geht, also:

 

Zahl

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

...

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

 

Das erste ist einfach:

DATA zahl;
DO i = 1 to 16;
output;
END;

 

Ich dachte an sowas wie Do until end of file, quasi Schleifen ineinander. Hab es erst mal so gemacht:


Data mega;
DO j = 1 to 1963;

DO i = 1 to 16;
output;
END;

END;

RUN;

 

Data mega2;
SET mega;

IF i in (1, 3, 12) THEN DELETE;

RUN;

 

Das funktioniert zwar aber besser wäre es dies automatisch in die bestehende Datei einzufügen und zwar nicht von i bis 1963 sondern end of file oder count(zeilen), denn mit der Zeit werden es immer mehr. Im zweiten Fall fehlen ein paar Zahlen, da müssen 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16 immer wiederholt werden.

1 AKZEPTIERTE LÖSUNG

Akzeptierte Lösungen
FreelanceReinh
Jade | Level 19

Hallo @Dvdscot,

 

es soll eine Zahlenfolge wiederholt werden? Darin ist die MOD-Funktion gut. Die Werte von MOD(n, k) für n = 0, 1, 2, 3, ... lauten nämlich 0, 1, ..., k−1, 0, 1, ..., k−1, 0, 1, ..., k−1 usw.: Wiederholungen von k verschiedenen Zahlen. Damit sich genau 16 verschiedene Zahlen wiederholen, sollte also k=16 gewählt werden. Der "natürliche" Wertebereich 0, ..., 15 kann durch nachträgliche Addition von 1 auf die gewünschte Zahlenfolge 1, ..., 16 verschoben werden. Für das erste Argument, n, eignet sich die Zeilennummer der bestehenden Datei -- aber nur fast, denn die beginnt mit 1, nicht mit 0. Wir müssen also von der Zeilennummer 1 abziehen.

 

Beispiel: Die 428 Sätze von SASHELP.CARS sollen vorne mit einer Nummer i = 1, 2, ..., 16, 1, 2, ..., 16 usw. versehen und die so entstehenden 16er-Blöcke mit j = 1, 2, 3, ... durchnummeriert werden. (Der letzte Block, mit der Nummer j=ceil(428/16)=27, hat nur 12 Sätze, denn 428=26*16+12.)

data want1;
i=mod(_n_-1,16)+1;
j+(i=1);
set sashelp.cars;
run;

Die automatische Variable _n_ zählt zwar, genau genommen, die Iterationen des Datasteps, aber in diesem einfachen Fall entspricht das einer Zählung der Sätze des Datasets im SET-Statement. Die "Blocknummer" j wird immer um 1 hochgezählt, wenn i=1 ist, also am Anfang jedes Blocks.

 

Im zweiten Fall soll eine Folge von 13 "willkürlich" gewählten Zahlen wiederholt werden? Also bietet sich dort k=13 an. Die Zuordnung von 0, 1, ..., 12 ("natürlicher" Wertebereich) zu den Elementen der gewünschten Folge 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16 gelingt diesmal nicht ohne weiteres durch eine einfache Addition, Subtraktion o. ä. Mit einem (temporären) Array aus 13 numerischen Elementen lässt sich aber jede beliebige Folge von 13 Zahlen zuordnen. Das obige Beispiel kann somit wie folgt abgewandelt werden:

data want2;
array _t[13] _temporary_ (2 4 5:11 13:16);
i=_t[mod(_n_-1,13)+1];
j+(i=2);
set sashelp.cars;
run;

 

Das ARRAY-Statement, in Langform geschrieben:

array _t[13] _temporary_ (2 4 5 6 7 8 9 10 11 13 14 15 16);

belegt die Array-Elemente _t[1], ..., _t[13] mit den Startwerten 2, 4, 5 usw. (die auch durch Kommas getrennt werden dürften). Der für jeden Satz berechnete Index mod(_n_-1,13)+1 in den eckigen Klammern ist analog zum ersten Beispiel gebildet, durchläuft also periodisch die Zahlen von 1 bis 13, und das Array _t sorgt für die gewünschte Zuordnung. Da es nur temporär ist, bleiben keine Hilfsvariablen in Dataset WANT2 zurück. Alternativ könnte man das Array von 0 bis 12 nummerieren -- array _t[0:12] -- und dann die "+1" im Zuweisungsstatement weglassen: i=_t[mod(_n_-1,13)];. Diesmal markiert i=2 den Beginn eines Blocks. Man könnte den Beginn aber stattdessen auch an _n_ ablesen, etwa j+(mod(_n_-1,13)=0); oder kürzer: j+~mod(_n_-1,13);.

Lösung in ursprünglichem Beitrag anzeigen

4 ANTWORTEN 4
FreelanceReinh
Jade | Level 19

Hallo @Dvdscot,

 

es soll eine Zahlenfolge wiederholt werden? Darin ist die MOD-Funktion gut. Die Werte von MOD(n, k) für n = 0, 1, 2, 3, ... lauten nämlich 0, 1, ..., k−1, 0, 1, ..., k−1, 0, 1, ..., k−1 usw.: Wiederholungen von k verschiedenen Zahlen. Damit sich genau 16 verschiedene Zahlen wiederholen, sollte also k=16 gewählt werden. Der "natürliche" Wertebereich 0, ..., 15 kann durch nachträgliche Addition von 1 auf die gewünschte Zahlenfolge 1, ..., 16 verschoben werden. Für das erste Argument, n, eignet sich die Zeilennummer der bestehenden Datei -- aber nur fast, denn die beginnt mit 1, nicht mit 0. Wir müssen also von der Zeilennummer 1 abziehen.

 

Beispiel: Die 428 Sätze von SASHELP.CARS sollen vorne mit einer Nummer i = 1, 2, ..., 16, 1, 2, ..., 16 usw. versehen und die so entstehenden 16er-Blöcke mit j = 1, 2, 3, ... durchnummeriert werden. (Der letzte Block, mit der Nummer j=ceil(428/16)=27, hat nur 12 Sätze, denn 428=26*16+12.)

data want1;
i=mod(_n_-1,16)+1;
j+(i=1);
set sashelp.cars;
run;

Die automatische Variable _n_ zählt zwar, genau genommen, die Iterationen des Datasteps, aber in diesem einfachen Fall entspricht das einer Zählung der Sätze des Datasets im SET-Statement. Die "Blocknummer" j wird immer um 1 hochgezählt, wenn i=1 ist, also am Anfang jedes Blocks.

 

Im zweiten Fall soll eine Folge von 13 "willkürlich" gewählten Zahlen wiederholt werden? Also bietet sich dort k=13 an. Die Zuordnung von 0, 1, ..., 12 ("natürlicher" Wertebereich) zu den Elementen der gewünschten Folge 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16 gelingt diesmal nicht ohne weiteres durch eine einfache Addition, Subtraktion o. ä. Mit einem (temporären) Array aus 13 numerischen Elementen lässt sich aber jede beliebige Folge von 13 Zahlen zuordnen. Das obige Beispiel kann somit wie folgt abgewandelt werden:

data want2;
array _t[13] _temporary_ (2 4 5:11 13:16);
i=_t[mod(_n_-1,13)+1];
j+(i=2);
set sashelp.cars;
run;

 

Das ARRAY-Statement, in Langform geschrieben:

array _t[13] _temporary_ (2 4 5 6 7 8 9 10 11 13 14 15 16);

belegt die Array-Elemente _t[1], ..., _t[13] mit den Startwerten 2, 4, 5 usw. (die auch durch Kommas getrennt werden dürften). Der für jeden Satz berechnete Index mod(_n_-1,13)+1 in den eckigen Klammern ist analog zum ersten Beispiel gebildet, durchläuft also periodisch die Zahlen von 1 bis 13, und das Array _t sorgt für die gewünschte Zuordnung. Da es nur temporär ist, bleiben keine Hilfsvariablen in Dataset WANT2 zurück. Alternativ könnte man das Array von 0 bis 12 nummerieren -- array _t[0:12] -- und dann die "+1" im Zuweisungsstatement weglassen: i=_t[mod(_n_-1,13)];. Diesmal markiert i=2 den Beginn eines Blocks. Man könnte den Beginn aber stattdessen auch an _n_ ablesen, etwa j+(mod(_n_-1,13)=0); oder kürzer: j+~mod(_n_-1,13);.

Oligolas
Barite | Level 11

Hi,

meinst Du sowas?

data want;
   length id 8;
   set sashelp.class;
   id+1;
   if id eq 17 then id=1;   
run;

Bitte bedenke, Du kannst Dir nicht einfach id basteln um Datasets zusammenzufügen. Es muss inhaltlich auch passen.

 

 

________________________

- Cheers -

Dvdscot
Obsidian | Level 7
Danke, der Indikator ist einer von mehreren Faktoren, es handelt sich um einen Datensatz der getrennt und dann wieder vereint wurde.
andreas_lds
Jade | Level 19

Du schreibst:

ich hab mehrere große Datensätze, damit ich die einfach kombinieren kann, will ich in beide Indikatoren einbauen. Ursprünglich hab ich einen Datensatz aufgeteilt und transponiert.

Warum wurde der Datensatz aufgeteilt? Es wäre vermutlich einfacher, wenn das Aufteilen überhaupt erforderlich ist, an dieser Stelle eine ID-Variable hinzufügen.