LesezeichenAbonnierenRSS-Feed abonnieren
Swen
Explorer | Level 4

Hallo,

 

ich habe mal wieder ein "Problem" in SAS und hoffe auf eure Hilfe.

 

Ich arbeite mit einem großen Datensatz der Angaben zu Steuerpflichtigen enthält. Da ein Steuerpflichtiger im Falle der Zusammenveranlagung aus zwei Personen besteht ist jedes Merkmal doppelt vorhanden. Einmal für Person A und einmal für Person B. Ich möchte einige Auswertungen auf Personenebene durchführen. Die Auswertungen erledige ich im Wesentlichen mit PROC tabulate. Dazu möchte ich nicht die Merkmale für Person A und B getrennt auswerten, sondern zusammen. Ich dachte, es sei der einfachste Weg die Merkmale für die Personen A und B untereinander zu kopieren.

 

Bitte schaut euch den angehangenen Screenshot an. Dort habe ich die Aufgabe veranschaulicht.

 

Wenn der Datensatz so strukturiert wird wie im Screenshot, kann ich die Variablen "Einkommen" und "MerkmalX" einfach mit den Standard-Methoden auswerten und bekomme so eine gemeine Auswertung der Merkmale für Person A und B.

 

Wie kann ich die Daten wie veranschaulicht untereinanderkopieren? Gibt es möglicherweise eine bessere/einfachere Lösung die ich nicht auf dem Schirm habe?

 

Vielen Dank

Swen


Datensatz.PNG
7 ANTWORTEN 7
Sebastian_R
Calcite | Level 5

Hallo Swen,

 

spontan habe ich zwei Ideen:

 

data ergebnis;

  set eingabe(keep=einkommen_a merkmalX_a rename=(einkommen_a=einkommen merkmalX_a=merkmalX))

        eingabe(keep=einkommen_b merkmalX_b rename=(einkommen_b=einkommen merkmalX_b=merkmalX));

run;

 

So stehen die Daten wie im Screenshot in Blöcken untereinander.

 

data ergebnis(keep=einkommen merkmalX);

  set eingabe;

  einkommen = einkommen_a;

  merkmalX = merkmalX_a;

  output;

  einkommen = einkommen_b;

  merkamlX = merkmalX_b;

  output;

run;

 

So stehen die beiden zusammengehörigen Datensätze direkt nacheinander.

 

Wenn es sich um viele Variablen handelt, kann man mit einem Proc Contents und einem Makro die Generierung des DataSteps und der Rename-Statements bzw. der Zuweisungen auch noch automatisieren (wenn man ein Namensmuster definieren kann).

 

Viele Grüße

Sebastian

 

CKothenschulte
Obsidian | Level 7

Hier noch meine Lösung mit minimalen Testdaten:

 

data DATEN;

input Einkommen_A Einkommen_B MerkmalX_A MerkmalX_B;

cards;

1 2 3 4

5 6 7 8

;;;;

run;

data DATEN_NEU;

  attrib Einkommen format=8.;

  attrib MerkmalX format=8.;

  set DATEN (rename=(Einkommen_A=Einkommen MerkmalX_A=MerkmalX) keep=Einkommen_A   MerkmalX_A)

      DATEN (rename=(Einkommen_B=Einkommen MerkmalX_B=MerkmalX) keep=Einkommen_B MerkmalX_B);

run;

 

Viel Erfolg!

HeideTribius
Fluorite | Level 6

die Lösung gefällt mir gut.

 

Swen müsste allerdings über eine Where-Bedinung dafür sorgen, dass die Fälle ohne Zusammenveranlagung sicherlich nicht zu leeren Datensätzen führen sollen:

data daten;
   input einkommen_a einkommen_b merkmalx_a merkmalx_b;
   cards;
   1 2 3 4
   5 6 7 8
   9 . 11 .
   ;
run;
 
data daten_neu;
  set daten (rename=(einkommen_a=einkommen merkmalx_a=merkmalx) keep=einkommen_a merkmalx_a)
      daten (rename=(einkommen_b=einkommen merkmalx_b=merkmalx) keep=einkommen_b merkmalx_b where=(einkommen));
  format einkommen commax16.2 merkmalx 8.;
run;
FreelanceReinh
Jade | Level 19

Hallo Swen,

 

für mehr als zwei zu transponierende Variablen könnte man auch Arrays verwenden:

 

/* Erzeugen von Testdaten */

data original;
do _n_=1 to 10;
  Einkommen_A=ranuni(1);
  Einkommen_B=ranuni(1);
  MerkmalX_A=ranuni(1);
  MerkmalX_B=ranuni(1);
  MerkmalY_A=ranuni(1);
  MerkmalY_B=ranuni(1);
  MerkmalZ_A=ranuni(1);
  MerkmalZ_B=ranuni(1);
  output;
end;
run;

/* Transponieren */

data ziel;
set original; 
array e Einkommen:;
array x MerkmalX:;
array y MerkmalY:;
array z MerkmalZ:;

do i = 1 to 2;
  Einkommen=e[i];
  MerkmalX=x[i];
  MerkmalY=y[i];
  MerkmalZ=z[i];
  output;
end;

keep Einkommen--MerkmalZ;
run;

Wenn es viele (numerische) Merkmale sind, könnte man auch alle zu einem zweidimensionalen Array zusammenfassen und sich so die vielen einzelnen ARRAY-Statements sparen.

jh_ti_bw
Obsidian | Level 7

Hallo Reinhard, hallo Swen,

 

für viele (numerische) Variablen kann man die Arrays auch nach den Kategorien anordnen:

data DATEN;
  input Einkommen_A Einkommen_B MerkmalX_A MerkmalX_B;
  cards;
  1 2 3 4
  5 6 7 8
  . 9 . .
run;
Data Daten_neu;
  keep Kat Einkommen   MerkmalX;

  set Daten;

  array inA Einkommen_A MerkmalX_A;
  array inB Einkommen_B MerkmalX_B;
  array out Einkommen   MerkmalX;

  kat = "A";
  do i = 1 to dim(out);
    out[i] = inA[i];
  end;
  if n(of out{*}) then output; 

  kat = "B";
  do i = 1 to dim(out);
    out[i] = inB[i];
  end;
  if n(of out{*}) then output; 
run;

Viele Grüße

 

Jan

Swen
Explorer | Level 4

Hallo,

 

@Sebastian_R @CKothenschulte:

Die Lösung gefällt mir sehr gut. Schön einfach! Vielen Dank!

 

@HeideTribius:

Du hast vollkommen recht. Das hatte ich bisher nicht auf dem Schirm. Natürlich sollten die Merkmale für Person B nur für den Fall der Zusammenveranlagung kopiert werden. Dabei ist ist ein nächstes Problem aufgetreten was ich nicht bedacht hatte. Unabhängig von der Veranlagungsart stehen die Angaben zu Frauen grundsätzlich in den Merkmalen für Person B. D.h. ich muss für den Fall der Einzelveranlagung noch nach dem Geschlecht differenzieren.

 

Meine Lösung sieht vereinfacht in etwa so aus:

data daten_neu;
  set daten (rename=(einkommen_a=einkommen merkmalx_a=merkmalx) keep=einkommen_a merkmalx_a where=(d_zusva=0 AND d_sex=0))
      daten (rename=(einkommen_b=einkommen merkmalx_b=merkmalx) keep=einkommen_b merkmalx_b where=(d_zusva=0 AND d_sex=1))
      daten (rename=(einkommen_a=einkommen merkmalx_a=merkmalx) keep=einkommen_a merkmalx_a where=(d_zusva=1))
      daten (rename=(einkommen_b=einkommen merkmalx_b=merkmalx) keep=einkommen_b merkmalx_b where=(d_zusva=1));
run;

So klappt alles wunderbar. Inwieweit ich das Vorgehen automatisieren kann, muss ich noch prüfen. Die pragmatische Lösung ist erstmal sich auf wirklich benötigte Variablen per Copy&Paste zu beschränken. 😉

 

@FreelanceReinh @jh_ti_bw:

Vielen Dank für euren Lösungsvorschlag. Mit Arrays habe ich mich bisher nie beschäftigt. Daher kann ich den Code nicht wirklich nachvollziehen und würdigen 😞

 

Viele Grüße und vielen Dank

Swen

HeideTribius
Fluorite | Level 6

hallo Swen,

 

dann reicht es eigentlich, wenn Du es bei zwei mal einlesen belässt und für das erste Dataset auch die Where-Bedingung definierst:

data daten_neu;
  set daten (rename=(einkommen_a=einkommen merkmalx_a=merkmalx) keep=einkommen_a merkmalx_a where=(einkommen))
      daten (rename=(einkommen_b=einkommen merkmalx_b=merkmalx) keep=einkommen_b merkmalx_b where=(einkommen));
run;

 

Die vielen Möglichkeiten im SAS sind wirklich verwirrend Smiley (zwinkernd)

 

viele Grüße und viel Erfolg! Heide

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
  • 7 Antworten
  • 3056 Aufrufe
  • 3 Kudos
  • 6 in Unterhaltung