invisible header

Das SHP ist ein in mehrere Teildatensätze aufgegliederter Datensatz. Es gibt Personendatensätze, Haushaltsdatensätze, generierte Daten, Biographiedaten etc. Diese Struktur stellt in der Datenaufbereitung eine besondere Herausforderung dar, weil wir meistens Variablen aus unterschiedlichen Teildatensätzen für unsere Analysen benötigen, die also miteinander verknüpft bzw. in einer Analysematrix zusammengeführt werden müssen.

Den SHP gibt es zudem, anders als z.B. den European Social Survey, immer nur als Komplettpaket - also alle Erhebungsjahre übergreifend. Durch diese “doppelte” Ausdifferenzierung des SHP (nach Datentyp und Erhebungsjahr) ergibt sich eine ziemlich umfangreiche und auf den ersten Blick überwältigende Datenlieferung.

Beachtet, dass die Versionsbezeichnung der Daten zumeist das Jahr der Bereitstellung, nicht das Erhebungsdatum der enthaltenen Variablen kennzeichnet. Wenn ihr also einen SHP-Datenordner mit der Kennnung “W21” öffnet, findet Ihr hierin die im Jahr 2021 bereitgestellten (nicht erhobenen) Daten, die sich auf das Erhebungsjahr 2019 beziehen.

Der Prozess der Datenaufbereitung, den dieses Skript dokumentiert, ist auf die in den Beispielanalysen benötigten Variablen ausgerichtet. Neben Standardvariablen (Einkommen, Lebenszufriedenheit, Bildung, Erwerbsstatus, Zivilstand) aus dem generierten Personendatensatz shpequiv_2017 werden Variablen aus dem Haushaltsdatensatz shp17_h (zur aktuellen Wohnsituation) angespielt. Zu Demonstrationszwecken fügen wir Variablen aus zwei weiteren Teildatensäten hinzu: das Bildungsniveau der Eltern aus dem “Social Origin”-Datensatz shp_so, sowie, für potentielle längsschnittliche Datenanalysen, die Lebenszufriedenheitswerte aus den Vorjahreserhebungen in den Files shpequiv_2016 und shpequiv_2015.

Um die hier dokumentierte Datenaufbereitung am eigenen Rechner nachzubilden, benötigt ihr den SHP-Datensatz. Details zu Bezug, Dokumentation und Installation der Daten findet Ihr hier. Achtung: Die auf dieser Webseite dargestellten Daten beziehen sich auf das Jahr 2017 (W19), stammen aber aus einer neueren SHP Version (Living in Switzerland Waves 1-23). Sofern ihr mit einer anderen Version als dieser arbeitet, können sich insb. Pfadnamen und Dateiordner, aber auch Variablenverteilungen (geringfügig) von den hier dargestellten Anweisungen und Ergebnissen unterscheiden.

Los geht’s, wie immer, mit dem Skriptkopf:

# BAa
# Beispielskript für SHP Aufbereitung
# Datum: 1.3.2023
# Autor: Marco Giesselmann

Als nächstes lesen wir die Daten ein und aktivieren die nötigen Packages. Vorab müsst ihr noch den von SWISSbase downgeloadenen Ordner extrahieren bzw. den dort enthaltenen Unterordner Data STATA in eure Ordnerstruktur einpflegen (z.B. “C:/Daten/SHP/Data STATA”).

Als Fundament der Variablenkollekte dient uns der Datensatz shpequiv_2017. Dieser enthält eine Sammlung generierter (sprich: benutzerfreundlich aufbereiteter) Kernvariablen des SHP 2017. Eine Übersicht zu den hier enthaltenen Variablen findet Ihr auf der Homepage des CNEF-Projektes. In den meisten Fällen werden die hierin enthalten Variablen nicht alle benötigen Merkmale abdecken, aber ein solides Variablenfundament bereitstellen.

Im SHP-Ordner Data STATA findet Ihr shpequiv_2017 sowie die anderen jahresspezifisch aufgegliederten Teildatensätze mit generierten Variablen direkt im Unterordner SHP-Data-CNEF-STATA. Hinweis: Ein ebenfalls üblicher alternativer Workflow würde an dieser Stelle mit dem Stammdatensatz shp_mp im Unterordner SHP-Data-WA-STATA starten.

# ... hier den Pfad zu den SHP Daten spezifizieren (z.B. "C:/Daten/SHP/Data_STATA/")
setwd("mein_laufwerk/mein_SHP_datenverzeichnis/")
# Daten einlesen
library(haven)
shp_base <- read_dta("SHP-Data-CNEF-STATA/shpequiv_2017.dta")
# install.packages("package")
library(tidyverse)
library(haven)
library(dplyr)
library(naniar)
library(Hmisc)
library(labelled)
library(summarytools)

 

1 Datenidentifikation und Datenauswahl

die shp_base benannte Datenmatrix enthalt nun alle 69 Variablen aus dem shpequiv_2017-Datensatz und Messungen von Insgesamt 13.949 Personen:

dim (shp_base)
## [1] 13949    69
View (shp_base)

Durch Recherche auf der SHP-Homepage oder in der mitgelieferten SHP-Dokumentation wisst ihr möglicherweise bereits, welche Variablen in den verschiedenen Teildatensätzen des SHP enthalten sind. Insbesondere solltet ihr wissen, wie die für eure Analyse wichtigen Variablen heissen. Diese “Best Practice” trifft allerdings häufig auf eine Dokumentationsrealität und Datenkomplexität, welche der prä-ante Variablenrecherche den Charakter einer Odysee verleihen.

Es ergibt daher Sinn, sich mit solchen R-Kommandos auseinanderzusetzen, die einen umfassenden Überblick zu den Variablen eines Datensatzes bieten. Insbesondere bei gut gelabelten Datensätzen - wie dem SHP - kann die datennahe Variableninspektion so häufig die Recherche in den flankierenden Dokumenten und Tools ersetzen (oder zumindest ergänzen). Berücksichtigt allerdings, dass bestimmte Merkmale zwar regelmässig, aber nicht jährlich im SHP erhoben werden (z.B. Netzwerke). Wenn Ihr also ausschliesslich auf die Daten eines bestimmten Jahres schaut, kann es sein, dass Euch ein zentraler Indikator durch die Lappen geht.

Eine sehr einfache, aber häufig schon ausreichende Übersicht bietet das Kommando contents aus dem Hmisc-package.

contents (shp_base)

Alternativ empfehlen wir den Befehl look_for aus dem labelled-package. Hier erhaltet Ihr einen vollständigen Überblick zu allen Metainformationen (Variablenlabel, Ausprägungen, Wertelabel) des Datensatzes.

look_for (shp_base)

Besonders praktisch: Über den Zuweisungspfeil lässt sich mit look_for (bei gut gelabelten Datensätzen) ein Codebook als Objekt bzw. Tabelle anlegen:

codebook<-look_for (shp_base)

Die hiermit erzeugte Tabelle könnt ihr aufrufen und dann leicht mit der Lupe rechts oben nach Schlagworten durchsuchen (z.b. marital, employment, education etc.) - und so die für Euch wichtigen Variablen identifizieren. Funktioniert natürlich nur auf sorgfältig und umfassend gelabelten Datensätzen.

 

2 Stichprobe definieren

Gerade bei komplexen Datenaufbereitung ist es oft hilfreich, den Ausgangsdatensatz frühzeitig auf die anvisierte Grundgesamtheit hin einzugrenzen. Oft - allerdings nicht immer! - besteht Eure Grundgesamtheit aus erwachsenen Personen in privaten Haushalten. Das SHP erhält allerdings auch Messungen von Personen unter 18 Jahren:

table (shp_base$d11101_2017)
## 
##  -2   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18 
##  16  95 100 100 119 119 126 130 128 139 121 135 155 156 144 161 158 165 166 181 
##  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38 
## 170 196 157 187 166 165 177 162 160 153 158 142 147 124 126 108 132 126 134 117 
##  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58 
## 149 130 138 154 169 154 189 192 195 196 231 239 208 247 288 217 252 195 241 211 
##  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78 
## 208 223 169 217 200 209 187 180 212 179 180 195 192 189 149 164 130 147 128  88 
##  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95  96  97  99 
## 117  90  67  79  87  72  52  62  45  36  19  15  13   6   7   5   6   3   4   2

Folglich grenzen wir die Daten auf Personen ein, die mindestens 18 Jahre alt sind:

shp_base<-filter(shp_base, d11101_2017>=18)

Ebenfalls üblich ist die Begrenzung der Stichprobe auf Personen mit gültigen Interviews. In vielen Datensätzen (z.B. dem ESS) ist diese Begrenzung bereits im Prozess der Datenbereitstellung umgesetzt. Im SHP ist dies nur teilweise der Fall: Wer das individuelle Interview verweigert, aber in einem Befragungshaushalt mit mindestens einem erfolgreich Interviewten lebt, taucht als Person im SHP auf! Auf Basis der Variable status_2017 lassen sich diese Überhangsmessungen identifizieren:

freq (as_factor(shp_base$status_2017))
## Frequencies  
## 
##                                        Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------------------------------- ------- --------- -------------- --------- --------------
##            Individual Questionnaire    9029     78.40          78.40     78.40          78.40
##                 Proxy Questionnaire     309      2.68          81.09      2.68          81.09
##                 Grid only (refusal)    2178     18.91         100.00     18.91         100.00
##       Biographic Questionnaire only       0      0.00         100.00      0.00         100.00
##                                <NA>       0                               0.00         100.00
##                               Total   11516    100.00         100.00    100.00         100.00

…von den 11516 erwachsenen Personen im Datensatz haben 2178 kein gültiges Personeninterview absolviert (von weiteren 309 liegt lediglich ein ‘Proxy-Interview’ vor, welche wir aber, wie vom SHP empfohlen als gültig anerkennen). Wir schliessen daher diese 2176 Messungen aus dem Datensatz aus:

shp_base<-filter(shp_base, status_2017!=2)
dim (shp_base)
## [1] 9338   69

die shp_base benannte Datenmatrix enthält nun alle 69 Variablen aus dem shpequiv_2017-Datensatz und Messungen von Insgesamt 9338 Personen. Diese bilden unsere Stichprobe. Manchmal ist es hilfreich, unmittelbar nach der Stichprobenbegrenzung alle Stichprobeneinheiten zu kennzeichnen, damit wir sie nach folgenden Datenverknüpfungen weiterhin eindeutig und leicht identifizieren können. Daher weisen wir allen Beobachtungen des Stichprobendatensatzes in einer neu generierten Stichprobenvariable den Wert 1 zu:

shp_base$sample<-1

Um die Datenmatrix zudem übersichtlich zu halten, reduzieren wir auf die benötigten Variablen:

shp_base <- select(shp_base, x11101ll, w11101_2017, d11101_2017, d11109_2017, d11102ll, d11104_2017, d11106_2017, d11107_2017, e11103_2017, i11102_2017, idhous_2017, m11122_2017, m11123_2017, p11101_2017, m11126_2017, w11101_2017, l11101_2017, status_2017, sample, status_2017)

Der Datensatz ist jetzt entsprechend kürzer und schmaler:

dim (shp_base)
View (shp_base)
contents (shp_base)

 

3 Datenverknüpfungen

3.1 Verknüpfungen von Individualdaten mit Haushaltsdaten

Der Blick in die Dokumentation oder in die Datenmatrix zeigt, dass unsere reduzierte Basisdatenmatrix shp_base nun die grundlegenden demographischen und sozio-ökonomischen Standardvariablen enthält. Für eine geplante Mediationsanalyse zum Einkommenseffekt benötigen wir allerdings zusätzlich Variablen zur Wohnsituation. Recherchen in der SHP-Doku oder ad-hoc Inspektionen des Datensatzes offenbaren, dass sich diese im Haushaltsdatensatz shp17_h_user (im Unterordner *SHP-Data-W1-W19-STATA_2017*) befinden:

shp_hh <- read_dta("SHP-Data-W1-W23-STATA/W19_2017/shp17_h_user.dta")
View (shp_hh)
contents (shp_hh)

Mit look_for liesse sich auch hier wieder eine erfolgreiche Variablensuche lancieren (z.B. im Suchmodus mal accommodation oder condition eingeben):

codebook_hh <- look_for (shp_hh)

Wie können wir nun Variablen aus der importierten Haushaltsdatenmatrix shp_hh in die Basismatrix shp_base integrieren? Konzeptionell ist der Lösungsweg eindeutig:

  • Neben der Personennummer enthält der Personendatensatz shp_base auch eine Variable Haushaltsnummer, die kennzeichnet, in welchem Haushalt eine Person im Jahr 2017 lebt
  • So lässt sich jede Information aus dem Haushaltsdatensatz (z.B. “Der Haushalt mit der Haushaltsnummer idhous17=51 bewohnt eine Wohnung mit h17h20=4 Räumen”) den entsprechenden Haushaltsmitgliedern im Basisdatensatz zuordnen (“…folglich wohnen die Personen mit den Personennummern 5101 und 5104 in einer Wohnung mit 4 Räumen”)

Systematisch lässt sich diese Operation in R über die join-Befehle aus dem dplyr-package umsetzen:

  • Hierbei werden Variablen aus dem anzufügenden Datensatz zeilengetreu, entsprechend der Ausprägung einer Schlüsselvariable (hier: der Haushaltsnummer) in den Ausgangsdatensatz integriert
  • Vorab ist es wichtig zu prüfen, dass die Schlüsselvariable in beiden Datensätzen
    • vorhanden ist (check: view (shp_hh) oder content(shp_hh))
    • identisch benannt ist (sonst muss, wie in diesem Beispiel, vor der Verknüpfung noch eine Umbenennung erfolgen)
    • keine Missings aufweist (sonst müssen entsprechende Zeilen vorab noch gelöscht werden); Check über summary(shp_hh$idhous_2017)
    • als identischer Variablentyp hinterlegt ist (check: class(shp_hh$idhous17)). Achtung: gelegentlich muss auch der Storage-Typ identisch sein - dann sollten beide Schlüsselvariablen “as.double” angelegt werden: shp_hh$idhous_2017<-as.double(shp_hh$idhous_2017)

Von den join-Befehlen gibt es mehrere Varianten, die jeweils unterschiedlich mit der Differenzmenge der verknüpften Datensätze umgehen (Differenzmenge: es gibt Personen in shp_base, für die liegen keine Haushaltsinformationen vor und es gibt wiederum Haushalte, die durch keine Person in shp_base repräsentiert werden)

Aus regressionsanalytischer Perspektive ist es weitgehend egal, wie wir mit dieser Differenzmenge umgehen (da wir letztlich nur solche Merkmalsträger in die Analyse aufnehmen, die in allen Kovariaten gültige Werte haben). Zum Workflow und mit Blick auf die Stichprobenstatistik passt es am besten, lediglich den Überhang des anzufügenden Datensatzes auszuschliessen und die nicht-verknüpfbaren Zeilen aus dem Basisdatensatz zu behalten. Dazu korrespondiert die Befehlsvariante left_join:

# Harmonisierung des Namens der Schlüsselvariablen
shp_hh$idhous_2017<-shp_hh$idhous17
# Verfugung der beiden Datensätze nach Schlüsselvariable
shp_base2<-left_join(shp_base, shp_hh, by="idhous_2017")
# Inspektion
View(shp_base2)
dim(shp_base2)
## [1] 9338  243

Im SHP ist die Schlüsselvariable in den beiden Datensätzen unterschiedlich benannt, so dass wir sie vor der Verknüpfung oben noch harmonisieren mussten (… wir hätten allerdings auch im Rahmen des join-Kommandos eine Harmonisierungsanweisung spezifizieren können). Dass die Verknüpfung wie gewünscht funktioniert hat, erkennen wir daran, dass

  • …die Fallzahl des neuen, kombinierten Basisdatensatzes shp_base2 der des alten shp_base entspricht, der Fälle-Überhang aus shp_hh also nicht in shp_base2 eingebunden wurde
  • …die Spaltendimension, also die Anzahl an Variablen der beiden Datensätze, sich aus Addition der Variablenanzahl der beiden Ausgangsdatensätze (abzüglich der Schlüsselvariable) ergibt
  • … die Personen mit Personennummer 5101 und 5104 nun tatsächlich in der Variable zur Wohnungsgrösse (Spalte 58) den Wert “4” zugewiesen bekommen haben … die visuelle Inspektion der beteiligten Datenmatrizen ist zur Fehleridentifikation, Fehleranalyse und Fehlervermeidung unverzichtbarer Bestandteil des Datenmanagements

Achtung: Hätten wir anstelle von left_join mit full_join gearbeitet, hätten wir nun auch diejenigen Messungen aus shp_hh in unserem Datensatz, die keinen Eintrag im Ausgangsdatensatz haben - also auch nicht zu unserer Stichprobe gehören. Wir könnten diese Messungen dann nun auf Basis der oben gebildeten “sample”-Variable eliminieren:

shp_base2<-filter(shp_base2, sample==1)
dim (shp_base2)
## [1] 9338  243

Variablenreduktion: Zwar bietet join die Option einer impliziten Variablenreduktion, wir nehmen die Variablenreduktion jedoch auch hier wieder manuell in einem separaten Schritt vor:

shp_base2 <- select(shp_base2, x11101ll, w11101_2017, d11101_2017, d11109_2017, d11102ll, d11104_2017, d11106_2017, d11107_2017, e11103_2017, i11102_2017, idhous_2017, m11122_2017, m11123_2017, p11101_2017, m11126_2017, w11101_2017, l11101_2017, h17h14, h17h20, h17h26, sample, status_2017)

 

3.2 Verknüpfungen von Individualdaten mit Individualdaten (Querschnitt)

Das eben praktizierte Prinzip könnten wir für weitere typische Verknüpfungsaufgaben anwenden.

Besonders einschlägig für soziologische Fragestellungen ist der SHP-Teildatensatz mit Informationen zur sozialen Herkunft. Dieser befindet sich im SHP-Unterordner SHP-Data-WA-STATA und heisst shp_so. Für einen Überblick zu seinem Variablenangebot nutzen wir wieder die Befehle content oder look_for.

shp_so <- read_dta("SHP-Data-WA-STATA/shp_so.dta")
contents (shp_so)

Der Teildatensatz shp_so enthält in erster Linie Variablen mit Informationen zu den Eltern der Befragungsperson und, ganz allgemein, zu den Lebensbedingungen der Befragungsperson, als sie 15 Jahre alt war.

Wenn wir nun Variablen aus dem Herkunftsdatensatz shp_so an unseren Basisdatensatz anspielen wollen - zum Beispiel um den Einfluss der politischen Position des Vaters (*shp_so: p__p46) auf die Lebenszufriedenheit (shpequiv_2017: p11101_2017*) zu analysieren - müssen wir beachten, dass wir nun nicht mehr Individual- mit Haushaltsinformationen, sondern mit weiteren Individualinformationen verknüpfen. Entsprechend ist die Schlüsselvariable der Operation dann nicht mehr die Haushaltsnummer, sondern die Personennummer.

Die Personennummer trägt im Basisdatensatz den Namen x11101ll. Auch hier müssen vor der Verknüpfung folglich die Namen der Schlüsselvariable harmonisiert werden:

shp_base2$idpers<-shp_base2$x11101ll

…nun können die Daten wiederum per left_join angefügt werden:

shp_base3<-left_join(shp_base2, shp_so, by="idpers")
View(shp_base3)

Nach erfolgter Verfugung könnten nun nicht nur Personen- und Haushaltsmerkmale, sondern auch Personen- und Elternmerkmale gemeinsam analysiert werden.

dim(shp_base3)
## [1] 9338   99

Achtung: In shp_so gibt es mehrere tausend Einträge von Personen, die kein Interview in 2017 absolviert haben und daher auch nicht zur Stichprobe gehören. Durch Verwendung des Befehls left_join wurden dieser Datenüberhang automatisch aussortiert - die Fallzahl liegt nach wie vor bei 9338. Hätten wir aber anstelle von left_join mit full_join gearbeitet, wären nun auch diejenigen Messungen aus shp_so in unserem Datensatz, die keinen Eintrag im Ausgangsdatensatz shp_base2 haben, wie folgender Befehl beispielhaft verdeutlicht:

testdata1<-full_join(shp_base2, shp_so, by="idpers")
dim(testdata1)
## [1] 31214    99

Es befänden sich nun mehr als 10000 Personen in unserem Datensatz, die nicht zur Stichprobe gehören! Insbesondere die Stichprobenstatistik wäre nun verzerrt. Wir müssten daher nun diesen Datenüberhang abschütteln und könnten dies leicht auf Grundlage der oben gebildeten “sample”-Variable:

testdata1<-filter(testdata1, sample==1)
dim (testdata1)
## [1] 9338   99

 

3.3 Verknüpfungen von Individualdaten mit Individualdaten (Längsschnitt)

Ein herausragendes Feature des SHP ist seine längsschnittliche Anlage: Personen werden mehrfach befragt, so kann Veränderung auf individueller Ebene gemessen und analytisch verwertet werden. Im Rahmen von BA-Arbeiten werden die längsschnittlichen Potentiale des SHP selten aufgegriffen - auch weil dafür weiterführende Analysetechniken notwendig sind. Die längsschnittliche Aufbereitung von Daten ist jedoch einfach.

Wir legen im ersten Schritt für jedes Jahr, welches in die längsschnittliche Analyse integriert werden soll, einen jahresspezifischen Datensatz an. Der Einfachheit halber nehmen wir an, dass der jahresspezifische Basisdatensatz ausschliesslich Daten aus shpequiv_JAHR enthält. Zudem nutzen wir lediglich drei Wellen.

shp_base_2016 <- read_dta("SHP-Data-CNEF-STATA/shpequiv_2016.dta")
shp_base_2016 <- select(shp_base_2016, x11101ll, w11101_2016, d11101_2016, d11109_2016, d11104_2016, d11106_2016, d11107_2016, e11103_2016, i11102_2016, idhous_2016, m11122_2016, m11123_2016, p11101_2016, m11126_2016, w11101_2016, l11101_2016, status_2016)

Wichtig: die Personennummer (hier: x11101ll), welche Befragte auch im Längsschnitt eindeutig identifiziert, muss immer mitgezogen werden. Wir schränken die Daten zudem, wie oben in Abschnitt 2, direkt auf Personen mit gültigem Interview ein und bilden eine Variable, welche diese Personen markiert:

dim (shp_base_2016)
## [1] 14960    16
shp_base_2016<-filter(shp_base_2016, d11101_2016>=18 & status_2016!=2)
shp_base_2016$sample_2016<-1
dim (shp_base_2016)
## [1] 9782   17

Nun noch das Gleiche für 2015:

shp_base_2015 <- read_dta("SHP-Data-CNEF-STATA/shpequiv_2015.dta")
shp_base_2015 <- select(shp_base_2015, x11101ll, w11101_2015, d11101_2015, d11109_2015, d11104_2015, d11106_2015, d11107_2015, e11103_2015, i11102_2015, idhous_2015, m11122_2015, m11123_2015, p11101_2015, m11126_2015, w11101_2015, l11101_2015, status_2015)
dim (shp_base_2015)
## [1] 16343    16
shp_base_2015<-filter(shp_base_2015, d11101_2015>=18 & status_2015!=2)
shp_base_2015$sample_2015<-1
dim (shp_base_2015)
## [1] 10890    17

Als nächstes werden die drei jahresspezifischen Basisdatensätze miteinander verknüpft und dabei in einen längsschnittlichen Datensatz zusammengeführt. Schlüsselvariable ist dabei die Variable mit der Personen ID.

Achtung: In längsschnittlichen Datensätzen wollen wir in der Regel auch diejenigen Merkmalsträger repräsentiert wissen, die nur in einem der jahresbezogenen Basisdatensätze vorhanden sind. Daher führen wir hier einen “full_join”, keinen “left_join” durch.

shp_ld_wide<-full_join(shp_base, shp_base_2016)
## Joining with `by = join_by(x11101ll)`
shp_ld_wide<-full_join(shp_ld_wide, shp_base_2015)
## Joining with `by = join_by(x11101ll)`
View(shp_ld_wide)

Cool: full_join erkennt offenbar automatisch die Variable, welche die Personen-ID enthält (zumindest wenn es nur eine Variable gibt, die in beiden Datensätzen vorkommt).

In längsschnittlichen Analysen gehören üblicherweise alle Personen zur Stichprobe, die in mindestens einer der verfugten Wellen zur Grundgesamtheit gehören und in dieser ein gültiges Interview abgeliefert haben. Die Teilnahmebedingung lässt sich mit folgender Filteranweisung umsetzen:

dim (shp_ld_wide)
## [1] 12367    50
shp_ld_wide<-filter(shp_ld_wide, sample==1 | sample_2016==1 | sample_2015==1)
dim (shp_ld_wide)
## [1] 12367    50

…dadurch, dass wir die jahresspezifischen Datensätze schon vorher bereinigt hatten, ergibt sich hierdurch keine effektive weitere Bereinigung mehr - der Datensatz ist bereits entsprechend reduziert.

Einfache längsschnittliche Analysen können bereits mit diesem Datensatz durchgeführt werden: Wir bilden eine Variable, welche die Veränderung der Lebenszufriedenheit auf individueller Ebene zwischen 2015 und 2017 misst,

shp_ld_wide$change_ls<-shp_ld_wide$p11101_2017-shp_ld_wide$p11101_2015
View(shp_ld_wide)

und könnten nun beispielsweise analysieren, ob sich diese Veränderung zwischen verheirateten und unverheirateten Personen unterscheidet. Oder, noch sinnvoller: wie sich diese Veränderung zwischen Personen, die im Jahr 2016 geheiratet haben, und solchen, die im Jahr 2016 nicht geheiratet haben, voneinander unterscheidet (womit wir die Logik einer sog. Difference-in-Difference Analyse annähern). Achtung: Zuvor müssten allerdings noch die uncodierten Missings in den Ausgangsvariablen der Analyse bereinigt werden

In der empirischen Praxis werden längsschnittliche Datensätze vor der Analyse üblicherweise noch ins das long-Format umgeformt:

library (tidyr)
library(data.table)

rawfile_long1 <- melt(setDT(shp_ld_wide), 
                      id=c("x11101ll", "d11102ll"), 
                      measure=patterns("^d11101_", "^d11104_", "^d11106_", "^d11107_", "^d11109_", "^e11103_", "^i11102_", "^p11101_" , "^m11126_"), 
                      value.name=c("age", "famstat", "hhsize", "numchild", "educyrs", "emplstat", "hhinc", "lifesat", "health"), 
                      variable.name="year", na.rm=TRUE)
View(rawfile_long1)

Ein so im long-Format aufbereiteter (und bereinigter, siehe unten) Längsschnittdatensatz kann nun für längsschnittliche Analysen (Event-Designs, Panelregression) genutzt werden

 

3.4 Weitere Verknüpfungstypen

  • In vielen fortgeschrittenen sozialwissenschaftlichen Anwendungen spielen Verknüpfungen mit externen Datenquellen eine grosse Rolle. Häufig sind dabei Einbindungen externer Datenquellen gefordert, die sich ebenfalls mit dem vorgestellten join-Kommandos in R umsetzen lassen. Eine Standardanwendung wäre z.B. die Verknüpfung von Individualdaten mit kantonalen Indikatoren (z.B. Regierungspartei, Einwohnerdichte, Wirtschaftskraft): Hier müsste zunächst ein externer Datensatz mit Kantonaldaten, z.B. des Bundesamtes für Statistik, aufbereitet werden, um dann im zweiten Schritt per left_join über die Schlüsselvariable I11101_2017 (=KantonID) angefügt zu werden. Jeder Person im Datensatz würden dann die kantonalen Indikatorenwerte des Wohnkantons zugespielt werden.
  • So genannte “linked actor”-Designs lassen sich ebenfalls auf Basis der join-Befehle umsetzen. Dabei werden direkt erhobene Informationen von LebenspartnerIn, Kindern und Eltern auf Basis von Schlüsselvariablen der Ankerperson zugespielt. Entsprechende Personenzeiger, die für solche Verknüpfungsprozeduren als Schlüsselvariablen eingesetzt werden können, befinden sich im SHP im Datensatz shp_mp.

 

4 Bereinigen des Datensatzes

Nach einem kleinen Umweg rücken wir nun wieder die Aufbereitung der zusammengefügten Datenmatrix für die anstehenden Analysen in den Vordergrund. Viele der zuletzt erstellten Matrizen dienten lediglich Demonstrationszwecken und/oder werden nun nicht mehr gebraucht - wir löschen sie der besseren Übersicht halber aus dem Environment.

remove(shp_base3, shp_base_2015,shp_base_2016, shp_hh, shp_so, rawfile_long1, shp_ld_wide, codebook, codebook_hh)

 

4.1 Variablen Umbenennen

Die Variablen in unsere Basis-Datenmatrix sind zwar nutzungsfreundlich gelabelt, tragen aber keine eingängigen Namen. Wir nehmen daher etwas mühsame Umbenennungen vor:

shp_base2 <-rename (shp_base2, alter=d11101_2017, geschlecht=d11102ll, zivilstand=d11104_2017, hhgr=d11106_2017, numkids=d11107_2017, educyears=d11109_2017, erwerb=e11103_2017, hhnetto=i11102_2017, lifesat=p11101_2017, pid=x11101ll, zustand=h17h14, noise=h17h26, anz_zimmer=h17h20, weight=m11123_2017, height=m11122_2017, kanton=l11101_2017, health=m11126_2017)

 

4.2 Item-Missings rekodieren

Als nächstes nehmen wir uns die Item-Missings vor. Darunter verstehen wir einzelne fehlende Werte innerhalb einer grundsätzlich gültigen Messreihe: Personen nehmen an dem Interview teil, verweigern aber die Beantwortung einzelner Fragen - das Ergebnis sind Item-Missings.

Anders als Personen, die das Interview komplett verweigert haben, bleiben Antwortverweigerer Teil der Stichprobe und sind daher auch in der Stichprobenbereinigung (siehe oben, Abschnitt 2) nicht aussortiert worden. Zu beachten ist gleichwohl, dass fehlenden Werte im SHP mit negativen Zahlen codiert sind. Das wird schnell deutlich, wenn wir die Variablenverteilungen inspizieren:

summary(shp_base2)
##       pid             w11101_2017         alter         educyears    
##  Min.   :5.101e+03   Min.   :   0.0   Min.   :18.00   Min.   :-2.00  
##  1st Qu.:7.915e+06   1st Qu.: 407.4   1st Qu.:38.00   1st Qu.:12.00  
##  Median :2.133e+07   Median : 592.0   Median :53.00   Median :12.00  
##  Mean   :3.103e+07   Mean   : 723.3   Mean   :52.26   Mean   :13.76  
##  3rd Qu.:6.268e+07   3rd Qu.: 816.6   3rd Qu.:67.00   3rd Qu.:16.00  
##  Max.   :1.054e+09   Max.   :5205.8   Max.   :99.00   Max.   :21.00  
##    geschlecht      zivilstand         hhgr         numkids      
##  Min.   :1.000   Min.   :-2.00   Min.   : 1.0   Min.   :0.0000  
##  1st Qu.:1.000   1st Qu.: 1.00   1st Qu.: 2.0   1st Qu.:0.0000  
##  Median :2.000   Median : 1.00   Median : 2.0   Median :0.0000  
##  Mean   :1.542   Mean   : 1.55   Mean   : 2.6   Mean   :0.4417  
##  3rd Qu.:2.000   3rd Qu.: 2.00   3rd Qu.: 4.0   3rd Qu.:1.0000  
##  Max.   :2.000   Max.   : 5.00   Max.   :10.0   Max.   :8.0000  
##      erwerb          hhnetto         idhous_2017           height      
##  Min.   :-2.000   Min.   :      0   Min.   :      51   Min.   :-2.000  
##  1st Qu.: 1.000   1st Qu.:  55823   1st Qu.:   79211   1st Qu.: 1.640  
##  Median : 2.000   Median :  85428   Median :  213346   Median : 1.700  
##  Mean   : 2.002   Mean   :  95774   Mean   :  313594   Mean   : 1.614  
##  3rd Qu.: 3.000   3rd Qu.: 119627   3rd Qu.:  626831   3rd Qu.: 1.770  
##  Max.   : 3.000   Max.   :1530268   Max.   :10539611   Max.   : 2.060  
##      weight          lifesat           health           kanton     
##  Min.   : -2.00   Min.   :-2.000   Min.   :-2.000   Min.   : 1.00  
##  1st Qu.: 60.00   1st Qu.: 7.000   1st Qu.: 2.000   1st Qu.: 6.00  
##  Median : 70.00   Median : 8.000   Median : 2.000   Median :16.00  
##  Mean   : 69.26   Mean   : 7.776   Mean   : 1.989   Mean   :14.44  
##  3rd Qu.: 80.00   3rd Qu.: 9.000   3rd Qu.: 2.000   3rd Qu.:23.00  
##  Max.   :180.00   Max.   :10.000   Max.   : 5.000   Max.   :26.00  
##     zustand         anz_zimmer         noise            sample 
##  Min.   :-3.000   Min.   :-3.000   Min.   :-3.000   Min.   :1  
##  1st Qu.: 2.000   1st Qu.: 3.000   1st Qu.: 2.000   1st Qu.:1  
##  Median : 2.000   Median : 4.000   Median : 2.000   Median :1  
##  Mean   : 2.148   Mean   : 4.203   Mean   : 1.783   Mean   :1  
##  3rd Qu.: 2.000   3rd Qu.: 5.000   3rd Qu.: 2.000   3rd Qu.:1  
##  Max.   : 3.000   Max.   :10.000   Max.   : 2.000   Max.   :1  
##   status_2017          idpers         
##  Min.   :0.00000   Min.   :5.101e+03  
##  1st Qu.:0.00000   1st Qu.:7.915e+06  
##  Median :0.00000   Median :2.133e+07  
##  Mean   :0.03309   Mean   :3.103e+07  
##  3rd Qu.:0.00000   3rd Qu.:6.268e+07  
##  Max.   :1.00000   Max.   :1.054e+09

Von R werden die negativen Ausprägungen als realisierte numerische Werte gedeutet und z.B. bei der Berechnung von Mittelwerten und Regressionskoeffizienten fälschlicherweise einbezogen. Wir recodieren daher die Missings in das für R verständliche Format “NA” (…was eine überraschend prozesszeitaufwändige Prozedur ist):

shp_base2<-replace_with_na_all(shp_base2,
                    condition = ~.x %in% c(-8, -7, -6, -5, -4, -3, -2, -1))
summary(shp_base2)
##       pid             w11101_2017         alter         educyears   
##  Min.   :5.101e+03   Min.   :   0.0   Min.   :18.00   Min.   : 0.0  
##  1st Qu.:7.915e+06   1st Qu.: 407.4   1st Qu.:38.00   1st Qu.:12.0  
##  Median :2.133e+07   Median : 592.0   Median :53.00   Median :12.0  
##  Mean   :3.103e+07   Mean   : 723.3   Mean   :52.26   Mean   :13.8  
##  3rd Qu.:6.268e+07   3rd Qu.: 816.6   3rd Qu.:67.00   3rd Qu.:16.0  
##  Max.   :1.054e+09   Max.   :5205.8   Max.   :99.00   Max.   :21.0  
##                                                       NA's   :28    
##    geschlecht      zivilstand        hhgr         numkids           erwerb     
##  Min.   :1.000   Min.   :1.00   Min.   : 1.0   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:1.00   1st Qu.: 2.0   1st Qu.:0.0000   1st Qu.:1.000  
##  Median :2.000   Median :1.00   Median : 2.0   Median :0.0000   Median :2.000  
##  Mean   :1.542   Mean   :1.55   Mean   : 2.6   Mean   :0.4417   Mean   :2.004  
##  3rd Qu.:2.000   3rd Qu.:2.00   3rd Qu.: 4.0   3rd Qu.:1.0000   3rd Qu.:3.000  
##  Max.   :2.000   Max.   :5.00   Max.   :10.0   Max.   :8.0000   Max.   :3.000  
##                  NA's   :1                                      NA's   :5      
##     hhnetto         idhous_2017           height          weight      
##  Min.   :      0   Min.   :      51   Min.   :1.180   Min.   : 36.00  
##  1st Qu.:  55823   1st Qu.:   79211   1st Qu.:1.640   1st Qu.: 62.00  
##  Median :  85428   Median :  213346   Median :1.700   Median : 71.00  
##  Mean   :  95774   Mean   :  313594   Mean   :1.709   Mean   : 72.58  
##  3rd Qu.: 119627   3rd Qu.:  626831   3rd Qu.:1.780   3rd Qu.: 81.00  
##  Max.   :1530268   Max.   :10539611   Max.   :2.060   Max.   :180.00  
##                                       NA's   :297     NA's   :419     
##     lifesat           health          kanton         zustand     
##  Min.   : 0.000   Min.   :1.000   Min.   : 1.00   Min.   :1.000  
##  1st Qu.: 8.000   1st Qu.:2.000   1st Qu.: 6.00   1st Qu.:2.000  
##  Median : 8.000   Median :2.000   Median :16.00   Median :2.000  
##  Mean   : 8.081   Mean   :1.994   Mean   :14.44   Mean   :2.162  
##  3rd Qu.: 9.000   3rd Qu.:2.000   3rd Qu.:23.00   3rd Qu.:2.000  
##  Max.   :10.000   Max.   :5.000   Max.   :26.00   Max.   :3.000  
##  NA's   :313      NA's   :13                      NA's   :28     
##    anz_zimmer         noise           sample   status_2017     
##  Min.   : 1.000   Min.   :1.000   Min.   :1   Min.   :0.00000  
##  1st Qu.: 3.000   1st Qu.:2.000   1st Qu.:1   1st Qu.:0.00000  
##  Median : 4.000   Median :2.000   Median :1   Median :0.00000  
##  Mean   : 4.479   Mean   :1.792   Mean   :1   Mean   :0.03309  
##  3rd Qu.: 5.000   3rd Qu.:2.000   3rd Qu.:1   3rd Qu.:0.00000  
##  Max.   :10.000   Max.   :2.000   Max.   :1   Max.   :1.00000  
##  NA's   :346      NA's   :19                                   
##      idpers         
##  Min.   :5.101e+03  
##  1st Qu.:7.915e+06  
##  Median :2.133e+07  
##  Mean   :3.103e+07  
##  3rd Qu.:6.268e+07  
##  Max.   :1.054e+09  
## 

…jetzt sieht’s besser aus. Wenn Euch diese Prozedur zu lange dauert (nervt insbesondere, wenn viele Synatxdurchläufe notwendig sind), stehen folgende Alternativen zu Verfügug:

  • Die Prozedur wird dezidiert auf die Variablen im Datensatz - statt den ganzen Datensatz - angesetzt:
shp_base2<- replace_with_na(shp_base2, replace = list(alter = c(-3,-2,-1), zivilstand = c(-3, -2, -1), numkids = c(-3, -2, -1), erwerb=c(-3, -2, -1), height=c(-3, -2, -1), weight=c(-3,-2,-1), hhnetto=c(-3,-2,-1), lifesat=c(-3,-2,-1), health=c(-3,-2,-1)))
  • Ihr behelft Euch mit einer manuellen, package-unabhängigen Lösung (ohne Garantie, dass das immer funktioniert):
replace_with_na_all_2 <- function(df, formule) {
  df[rlang::as_function(formule)(df)] <- NA
  df
}
shp_base2<-replace_with_na_all_2(df = shp_base2, formule = ~.x == -1)
shp_base2<-replace_with_na_all_2(df = shp_base2, formule = ~.x == -2)
shp_base2<-replace_with_na_all_2(df = shp_base2, formule = ~.x == -3)
summary (shp_base2)
  • Ihr recodiert alle Variablen einzeln mit na_if

 

4.3 Weitere Rekodierungen

Häufig erfolgt die Rekodierung und Klassierung von Variablen erst unmittelbar vor der Analyse. Wir nehmen aber ein paar grundlegende Umformungen bereits hier vor. Dies, weil nach erfolgter Faktorisierung Variablenrekodierungen meist aufwändiger sind als davor.

Grundlegende Tipps für Rekodierungsarbeiten:

  1. nehme Rekodierung in einer neuen Variable vor, damit Ziel- und Bedingungsvariable nicht identisch sind (siehe auch Erläuterung unten).
  2. vergebe, wenn es sich um kategoriale Variablen handelt, bei Zuweisungen direkt Kategoriennamen statt numerischer Codes.
  3. inspiziere nach jedem Rekodierungsschritt die Datenmatrix.
  4. prüfe nach der Rekodierung die neue Variable umfassend (Verteilungseigenschaften, Häufigkeitsabgleich,…)

Für unsere Analyse benötigen wir das gewichtete Pro-Kopf Einkommen nach OECD-Skala, welches das Standardmass zur Messung von Wohlstand in Wissenschaft und Sozialberichterstattung ist. Diese Variable nutzen wir, um in der ersten Beispielanalyse den Effekt des Einkommens auf die Lebenszufriedenheit zu bestimmen. Der Indikator ergibt sich hier durch einfache algebraische Verknüpfungen der Ausgangsvariablen:

shp_base2$erwach<-shp_base2$hhgr-shp_base2$numkids 
shp_base2$oecd_weight<-1+(shp_base2$erwach-1)*0.5+shp_base2$numkids*0.3
shp_base2$hhnetto[shp_base2$hhnetto==0]<-NA # HH-Einkommen gleich Null -> unplausibler Wert
shp_base2$oecd_inc_mon<-(shp_base2$hhnetto)/shp_base2$oecd_weight/12

Zudem bilden wir aus der Kombination von Körpergewicht und Grösse eine Variable bmi, aus der wir wiederum eine Variable overweight ableiten. Diese Variable benötigen wir, um in der zweiten Beispielanalyse den Einfluss der Wohnungsgrösse auf die Wahrscheinlichkeit von Übergewicht zu bestimmen. Hier ergibt sich die neue Variable zusätzlich durch bedingte Zuweisung auf Basis der Ausgangsvariablen.

shp_base2$bmi<-shp_base2$weight/(shp_base2$height^2) 
shp_base2$overweight[shp_base2$bmi<30]<-0
shp_base2$overweight[shp_base2$bmi>=30]<-1
summary(shp_base2)
##       pid             w11101_2017         alter         educyears   
##  Min.   :5.101e+03   Min.   :   0.0   Min.   :18.00   Min.   : 0.0  
##  1st Qu.:7.915e+06   1st Qu.: 407.4   1st Qu.:38.00   1st Qu.:12.0  
##  Median :2.133e+07   Median : 592.0   Median :53.00   Median :12.0  
##  Mean   :3.103e+07   Mean   : 723.3   Mean   :52.26   Mean   :13.8  
##  3rd Qu.:6.268e+07   3rd Qu.: 816.6   3rd Qu.:67.00   3rd Qu.:16.0  
##  Max.   :1.054e+09   Max.   :5205.8   Max.   :99.00   Max.   :21.0  
##                                                       NA's   :28    
##    geschlecht      zivilstand        hhgr         numkids           erwerb     
##  Min.   :1.000   Min.   :1.00   Min.   : 1.0   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:1.00   1st Qu.: 2.0   1st Qu.:0.0000   1st Qu.:1.000  
##  Median :2.000   Median :1.00   Median : 2.0   Median :0.0000   Median :2.000  
##  Mean   :1.542   Mean   :1.55   Mean   : 2.6   Mean   :0.4417   Mean   :2.004  
##  3rd Qu.:2.000   3rd Qu.:2.00   3rd Qu.: 4.0   3rd Qu.:1.0000   3rd Qu.:3.000  
##  Max.   :2.000   Max.   :5.00   Max.   :10.0   Max.   :8.0000   Max.   :3.000  
##                  NA's   :1                                      NA's   :5      
##     hhnetto           idhous_2017           height          weight      
##  Min.   :    533.9   Min.   :      51   Min.   :1.180   Min.   : 36.00  
##  1st Qu.:  55898.0   1st Qu.:   79211   1st Qu.:1.640   1st Qu.: 62.00  
##  Median :  85540.2   Median :  213346   Median :1.700   Median : 71.00  
##  Mean   :  95856.5   Mean   :  313594   Mean   :1.709   Mean   : 72.58  
##  3rd Qu.: 119663.4   3rd Qu.:  626831   3rd Qu.:1.780   3rd Qu.: 81.00  
##  Max.   :1530268.4   Max.   :10539611   Max.   :2.060   Max.   :180.00  
##  NA's   :8                              NA's   :297     NA's   :419     
##     lifesat           health          kanton         zustand     
##  Min.   : 0.000   Min.   :1.000   Min.   : 1.00   Min.   :1.000  
##  1st Qu.: 8.000   1st Qu.:2.000   1st Qu.: 6.00   1st Qu.:2.000  
##  Median : 8.000   Median :2.000   Median :16.00   Median :2.000  
##  Mean   : 8.081   Mean   :1.994   Mean   :14.44   Mean   :2.162  
##  3rd Qu.: 9.000   3rd Qu.:2.000   3rd Qu.:23.00   3rd Qu.:2.000  
##  Max.   :10.000   Max.   :5.000   Max.   :26.00   Max.   :3.000  
##  NA's   :313      NA's   :13                      NA's   :28     
##    anz_zimmer         noise           sample   status_2017     
##  Min.   : 1.000   Min.   :1.000   Min.   :1   Min.   :0.00000  
##  1st Qu.: 3.000   1st Qu.:2.000   1st Qu.:1   1st Qu.:0.00000  
##  Median : 4.000   Median :2.000   Median :1   Median :0.00000  
##  Mean   : 4.479   Mean   :1.792   Mean   :1   Mean   :0.03309  
##  3rd Qu.: 5.000   3rd Qu.:2.000   3rd Qu.:1   3rd Qu.:0.00000  
##  Max.   :10.000   Max.   :2.000   Max.   :1   Max.   :1.00000  
##  NA's   :346      NA's   :19                                   
##      idpers              erwach       oecd_weight     oecd_inc_mon     
##  Min.   :5.101e+03   Min.   :1.000   Min.   :1.000   Min.   :   21.18  
##  1st Qu.:7.915e+06   1st Qu.:2.000   1st Qu.:1.500   1st Qu.: 3028.39  
##  Median :2.133e+07   Median :2.000   Median :1.500   Median : 4215.31  
##  Mean   :3.103e+07   Mean   :2.158   Mean   :1.712   Mean   : 4674.85  
##  3rd Qu.:6.268e+07   3rd Qu.:2.000   3rd Qu.:2.100   3rd Qu.: 5616.00  
##  Max.   :1.054e+09   Max.   :6.000   Max.   :3.900   Max.   :51020.34  
##                                                      NA's   :8         
##       bmi          overweight    
##  Min.   :13.06   Min.   :0.0000  
##  1st Qu.:21.78   1st Qu.:0.0000  
##  Median :24.21   Median :0.0000  
##  Mean   :24.77   Mean   :0.1058  
##  3rd Qu.:26.99   3rd Qu.:0.0000  
##  Max.   :66.79   Max.   :1.0000  
##  NA's   :503     NA's   :503

Bei solchen bedingten Zuweisungen setzt die Anweisung in der eckigen Klammern jeweils die Bedingung, nimmt also die Rolle der aus vielen Statistikprogrammen bekannten “if”-Anweisung ein. Innerhalb der Klammer liessen sich durch Verknüpfungen mit den Operatoren & (“und”) oder | (“oder”) auch mehrere Bedingungen kombinieren - beispielsweise wenn wir unterschiedliche Grenzwerte für Frauen und Männer definieren wollten.

Bedingte Zuweisungen können auch bei Klassierungen und anderen Variablenumformungen angewendet werden. Beispielsweise könnten wir bestrebt sein, bestimmte Kategorien der Variable zivilstand zusammenzufassen (konkret böte sich hier die Integration der Kategorien 4 und 5 an).

attributes(shp_base2$zivilstand)
## $label
## [1] "Marital Status of Individual"
## 
## $format.stata
## [1] "%56.0g"
## 
## $labels
##                                                  .S (-3) 
##                                                       -3 
##                                                  .M (-2) 
##                                                       -2 
##                                                  .C (-1) 
##                                                       -1 
##                         Married or Living with a Partner 
##                                                        1 
##                        Single, not Living with a Partner 
##                                                        2 
##                       Widowed, not Living with a Partner 
##                                                        3 
##                      Divorced, not Living with a Partner 
##                                                        4 
##   Separated (Legally Married), not Living with a Partner 
##                                                        5 
## Not Living with a Partner (Individuals age 18 and older) 
##                                                        6 
##     Not Living with a Partner (Individuals under age 18) 
##                                                        7 
## 
## $class
## [1] "haven_labelled" "vctrs_vctr"     "double"
freq (shp_base2$zivilstand)
## Frequencies  
## 
##               Freq   % Valid   % Valid Cum.   % Total   % Total Cum.
## ----------- ------ --------- -------------- --------- --------------
##           1   6299    67.463         67.463    67.456         67.456
##           2   1788    19.150         86.612    19.148         86.603
##           3    516     5.526         92.139     5.526         92.129
##           4    617     6.608         98.747     6.607         98.736
##           5    117     1.253        100.000     1.253         99.989
##        <NA>      1                              0.011        100.000
##       Total   9338   100.000        100.000   100.000        100.000

Wie auch in den anderen Kodierungsszenarien empfiehlt es sich hier, die Rekodierung in einer neuen Variable (und nicht in der Ausgangsvariable) vorzunehmen. Grund: Wenn Ziel- und Bedingungsvariable in der Zuweisung identisch sind, kann es oft zu zirkulären Umschreibeprozessen im Rahmen der sequentiellen Zuweisungsprozedur kommen. Daher:

shp_base2$zivilstand_class[shp_base2$zivilstand==1] <- "Married"
shp_base2$zivilstand_class[shp_base2$zivilstand==2] <- "Single"
shp_base2$zivilstand_class[shp_base2$zivilstand==3] <- "Widowed"
shp_base2$zivilstand_class[shp_base2$zivilstand==4 | shp_base2$zivilstand==5] <- "Separated/Divorced"
shp_base2$zivilstand_class[shp_base2$zivilstand==NA] <- NA #Eigentlich nicht nötig, da automatisch für alle nicht definierte Beobachtungen vergeben.

# Check! 
table (shp_base2$zivilstand_class, shp_base2$zivilstand, useNA="always")
##                     
##                         1    2    3    4    5 <NA>
##   Married            6299    0    0    0    0    0
##   Separated/Divorced    0    0    0  617  117    0
##   Single                0 1788    0    0    0    0
##   Widowed               0    0  516    0    0    0
##   <NA>                  0    0    0    0    0    1

Das tidyverse-Metapackage bietet verschiedene Alternativen zur zuweisungsbasierten Rekodierung. Mit der Funktion case_when liesse sich die oben durchgeführte Generierung mit exakt identischer Zielvariable wie folgt umsetzen:

shp_base2$zivilstand_class <- case_when (shp_base2$zivilstand == 1 ~ "Married",
                                    shp_base2$zivilstand == 2 ~ "Single",
                                    shp_base2$zivilstand == 3 ~ "Widowed",
                                    shp_base2$zivilstand == 4 | shp_base2$zivilstand ==5 ~ "Separated/Divorced",
                                    shp_base2$zivilstand == NA ~ NA)
# Check!
table (shp_base2$zivilstand_class, shp_base2$zivilstand, useNA="always" )
##                     
##                         1    2    3    4    5 <NA>
##   Married            6299    0    0    0    0    0
##   Separated/Divorced    0    0    0  617  117    0
##   Single                0 1788    0    0    0    0
##   Widowed               0    0  516    0    0    0
##   <NA>                  0    0    0    0    0    1

Die “case_when”- Funktionalität ist insbesondere dann wichtig, wenn nicht fixe, sondern variable Werte unter einer bestimmten Bedingung zugewiesen werden sollen. Ein typischer Fall stellt die Bildung einer elterlichen Bildungs- oder Statusvariable dar, die jeweils den Wert des höher gebildeten Elternteils übernehmen soll - oder die Überschreibung einer Variable mit einem Ersatzwert aus einer anderen Variable für die Fälle mit einem fehlenden Wert bzw. NA. In solchen Fällen funktioniert die mit einer eckigen Bedingungsklammer operierende einfache Lösung nicht, aber die “case_when”-basierte: hierin kann statt eines fixen Codes auch ein Variablenwert zugewiesen werden.

Geschafft! Der nervige Teil des Datenmanagements ist durch! Jetzt kann es an die Analysen gehen. Vorher vielleicht noch die nun analysebereite Datenmatrix abspeichern, damit wir nicht bei jedem Neustart den ganzen Aufbereitungscode von neuem durchlaufen lassen müssen:

# Daten schreiben (z.B. nach "c:\meine_BA")
write_dta(shp_base2, "mein_laufwerk/mein_zielverzeichnis/shp_base2.dta")

…wir empfehlen, die Daten im “.dta”-Format zu speichern und zu laden, da so die Wertelabel konserviert werden.

 

logo.utf8