SC6 merge

Hallo zusammen,

ich arbeite gerade an einem SC6 merge von spEmp, spUnemp, pTarget, spSchoolExtExam, Education und Basics. Da es sich um meinen ersten merge handelt, habe ich mich an einen vorherigen Blogbeitrag orientiert. ([SC6: merge - #2 von daniel.bela])

Mein Do-File sieht wie folgt aus: (anscheinend kann ich noch keine Dateien anfügen, also hier als Fließtext)


SC6_merge


clear all

set more off

global root „HIER EIGENEN LINK EINFÜGEN“

cd „$root“

cap: log using „SC6_merge_neu“, replace

**Episodendaten vorbereiten

  • SC6_spEmp_D_13-0-0

use SC6_spEmp_D_13-0-0, clear

keep ID_t splink spell subspell wave ts23203 ts23223_g1 ts23228 ts23235 ts23410_g1

keep if subspell==0
drop subspell

save „spEmp“, replace

use SC6_Biography_D_13-0-0, clear

keep if sptype == 26

merge 1:1 ID_t splink using „spEmp“, nogenerate assert(match using) keep(match)

generate enddate=ym(endy,endm)
generate startdate=ym(starty,startm)
generate duration=enddate-startdate+1
expand duration
bysort ID_t splink : generate intdate=startdate+_n-1
format enddate startdate intdate %tm

save „Episodendaten_Emp“, replace

  • SC6_spUnemp_D_13-0-0

use SC6_spUnemp_D_13-0-0, clear

keep ID_t splink spell subspell wave ts25208

keep if subspell==0
drop subspell

save „spUnemp“, replace

use SC6_Biography_D_13-0-0, clear

keep if sptype == 27

merge 1:1 ID_t splink using „spUnemp“, nogenerate assert(match using) keep(match)

generate enddate=ym(endy,endm)
generate startdate=ym(starty,startm)
generate duration=enddate-startdate+1
expand duration
bysort ID_t splink : generate intdate=startdate+_n-1
format enddate startdate intdate %tm

save „Episodendaten_Unemp“

**Querschnitts- und Paneldaten mergen

  • merge sSC6_spSchoolExtExam_D_13-0-0 + SC6_Education_D_13-0-0

use SC6_spSchoolExtExam_D_13-0-0, clear

merge 1:m ID_t exam using „SC6_Education_D_13-0-0“, nogen

keep ID_t exam wave ts11300 ts11308 ts1130y number splink tx28101 tx28103

save „merge_spSchoolExtExam_Education“, replace

  • merge SC6_Basics_D_13-0-0 + merge_spSchoolExtExam_Education
    use SC6_Basics_D_13-0-0, clear

merge 1:m ID_t using „merge_spSchoolExtExam_Education“, nogen

keep ID_t exam wave tx29003 tx29064 tx29068 ts11300 ts11308 ts1130y number splink tx28101 tx28103 tx29062

save „merge_spSchoolExtExam_Education_Basics“, replace

  • merge merge_Basics_spSchoolExtExam + SC6_pTarget_D_13-0-0
    use SC6_pTarget_D_13-0-0, clear

merge 1:1 ID_t wave using SC6_CohortProfile_D_13-0-0, nogenerate

keep ID_t wave t400500_g1 t400500_g3 t413500_v1 t514002 t514009 t515035 t700001 t70000y t724201 t725000 t731301_g1 t731301_g2 t731351_g2 t731401 t731402 t731404_v1 t731451 t731454_v1 t751001_g2 tx8600m tx8600y

merge 1:m ID_t wave using „merge_spSchoolExtExam_Education_Basics“, nogen

keep ID_t exam wave tx29003 tx29064 tx29068 ts11300 ts11308 ts1130y number splink tx28101 tx28103 tx29062 t400500_g1 t400500_g3 t413500_v1 t514002 t514009 t515035 t700001 t70000y t724201 t725000 t731301_g1 t731301_g2 t731351_g2 t731401 t731402 t731404_v1 t731451 t731454_v1 t751001_g2 tx8600m tx8600y

save „merge_spSchoolExtExam_Education_Basics_pTarget“, replace

**merge Querschnitts-/Paneldaten mit Episodendaten
use merge_spSchoolExtExam_Education_Basics_pTarget, clear

generate intdate=ym(tx8600m, tx8600y)
format %tm intdate

save merge_spSchoolExtExam_Education_Basics_pTarget_intdate, replace

use merge_spSchoolExtExam_Education_Basics_pTarget_intdate, clear

merge m:m ID_t intdate using „Episodendaten_Emp“, nogen keep(master match)

save „Quer+Panel+Emp“, replace

use Quer+Panel+Emp, clear

merge m:m ID_t intdate using „Episodendaten_Unemp“, nogen keep(master match)

keep ID_t wave tx29003 tx29064 tx29068 ts11300 ts11308 ts1130y splink tx28101 tx28103 tx29062 t400500_g1 t400500_g3 t413500_v1 t514002 t514009 t515035 t700001 t70000y t724201 t725000 t731301_g1 t731301_g2 t731351_g2 t731401 t731402 t731404_v1 t731451 t731454_v1 t751001_g2 spell ts25208 ts23203 ts23223_g1 ts23228 ts23235 ts23410_g1

save „Quer+Panel+Episoden“, replace

duplicates report ID_t wave
quietly : duplicates tag ID_t wave , generate(dups)
tabulate dups
keep if dups == 0

log close
clear all
exit

Meine Frage ist, ob der merge generell plausibel ist, vor allem in Hinsicht auf Panel- und Episodendaten, oder ob es noch Verbesserungspotenzial gibt, da es sich ja wie gesagt, um meinen ersten Merge handelt.

Ich freue mich auf eure Unterstützung.
Vielen Dank im Voraus!

Katharina

Liebe Katharina,
prinzipiell läuft deine Syntax offenbar schonmal durch, ohne Fehler zu produzieren. Das ist schonmal gut. Und wenn das dein erster merge-Versuch ist, dann bist du dafür schon sehr sehr weit gekommen ;-), denn genau genommen ist das ja nicht EIN Merge, sondern gleich ne ganze Menge.
Allerdings bin ich mir nicht wirklich sicher, ob für dich am Ende auch der Datensatz herauskommt, den du analysieren möchtest. Da du zu deinem Analyseziel und deiner -methode leider wenig Angaben gemacht hast, kann ich nur mutmaßen, welche Art von Datensatz du am Ende analysieren möchtest.
Eine der Hauptproblematiken, die ich in deiner Syntax gesehen habe, hat einfach mit der komplexen Datenstruktur der NEPS-Daten zu tun und viele Nutzer haben damit so ihre Schwierigkeiten, vor allem wenn sie so wie du Variablen aus derart vielen verschiedenen Datensätzen heranziehen wollen. Das wirklich Wesentlichste, was ich dir und anderen Mitlesern mit auf den Weg geben kann, ist, sich vor jedem Zwischenschritt und vor jedem Merge einmal genau zu überlegen, wie viele Zeilen pro Person oder pro Person und Welle die unterschiedlichen Datenquellen gerade haben (bzw haben sollen) und wie man dahin gelangt. Um am Ende noch plausibel analysierbare Daten zu haben, empfehlen wir zB immer, die Episodendaten erstmal so aufzuarbeiten, dass man VOR einem möglichen merge mit einem Paneldatensatz nur noch EINE Zeile pro Person in den Daten hat.
Ich habe mal versucht, deine Daten so aufzubereiten, wie ich es machen würde und dabei so viel wie möglich kommentiert. Vielleicht findest du da ein paar Hinweise und Anregungen…

clear all
set more off
local userpath "Y:\eigenerSpeicherort"
neps set study "SC6" version "13.0.0"  level "D" directory "XYZ:/SC6Daten/SUFdownload/13-0-0/Stata14", replace

// Aufbereitung der Episodendaten:
// benötigte Variablen:
// spEmp: ts23203 ts23223_g1 ts23228 ts23235 ts23410_g1
// spUnemp: ts25208
// Ich bereite sowohl die spEmp als auch spUnemp Daten erst auf und merge sie dann beide
// zusammen an Biography. Das ist etwas übersichtlicher ;-)
neps: use spEmp, clear
keep if subspell==0
keep ID_t splink spell subspell ts23203 ts23223_g1 ts23228 ts23235 ts23410_g1
// Für alle, die hier mitlesen: wertvoller Tipp am Rande, um eure persönlichen Ordner klein zu 
// halten und nicht mit Zwischenfiles aus der Datenaufbereitung zuzumüllen: die Stata-interne
// Funktion "tempfile" kann super gut dazu benutzt werden, Zwischendaten zu speichern und
// Stata kümmert sich nach Programmende selbst ums löschen ;-)
tempfile spEmp
save `spEmp'

neps: use spUnemp, clear
keep if subspell==0
keep ID_t splink spell subspell ts25208
tempfile spUnemp
save `spUnemp'

// Nun an Biography anmergen:
neps: use Biography, clear
merge 1:1 ID_t splink using `spEmp', nogenerate keep(master match)
// hier behält man natürlich erstmal die master (=alle Biography Fälle) und merge - Fälle
merge 1:1 ID_t splink using `spUnemp', nogenerate keep(master match)
keep if inlist(sptype,26,27)		// nun wird der Datensatz auf die interessierenden Fälle beschränkt

// für späteren Merge mit Paneldaten müssen die Daten nun anhand der Episodenzeiten
// umstrukturiert werden. So kann man die Information zum Zeitpunkt des Interviews anmergen
// (das wir hier zu diesem Zeitpunkt in diesem Datensatz noch nicht haben). Später wird über
// "intdate" gemerged und nur die match-Fälle behalten
generate enddate=ym(endy,endm)
generate startdate=ym(starty,startm)
generate duration=enddate-startdate+1
expand duration
bysort ID_t splink : generate intdate=startdate+_n-1
// Da es vereinzelt fehlende Start-und Enddatumsangaben gibt und damit kein "Interviewdatum"
// für den späteren Merge generiert werden kann, werden diese hier entfernt
drop if missing(intdate)
format enddate startdate intdate %tm
drop duration startdate enddate
tempfile Episodendaten
save `Episodendaten'

// Aufbereitung der Paneldaten
// spSchoolExtExam: ts11300 ts11308 ts1130y
// Education: tx28101 tx28103
// Basics: tx29003 tx29064 tx29068
// pTarget: t400500_g1 t400500_g3 t413500_v1 t514002 t514009 t515035 t700001 t70000y t724201 t725000 t731301_g1 t731301_g2 t731351_g2 t731401 t731402 t731404_v1 t731451 t731454_v1 t751001_g2
// CohortProfile: tx8600m tx8600y

// Bildungshistorie vorbereiten:
// im File Education sind sowohl alle Schulabschlüsse als auch die Abschlüsse im Ausland
// enthalten und bereits pro Person aufbereitet. Da hier jedoch mehrere Schulabschlüsse pro
// Person zu finden sind, sollte man sich VOR dem Merge auf die interessierenden beschränken.
// Ich gehe mal davon aus, dass der jeweils letzte Bildungsabschluss einer Person von
// Interesse ist. Falls das nicht so ist, müsste man an dieser Stelle nochmals gezielt überlegen,
// was man wann in welcher Form benötigt. Der Vollständigkeit halber sei an dieser Stelle
// ebenfalls angemerkt, dass der letzte Bildungsabschluss einer Person nicht zwangsläufig
// immer der höchste jemals erreichte ist. Sollte man diesen benötigen, müsste man ebenfalls
// die Datenauswahl anpassen!
neps: use Education
// so wird der jeweils letzte Abschluss innerhalb einer Person markiert
bysort ID_t (number): gen lastab = 1 if _n==_N	
keep if lastab ==1		// nur die letzten Abschlüsse behalten
// hier wird exam noch behalten, weil für alle Fälle, in denen ein externer Abschluss der letzte
// Abschluss war, nun noch die Zusatzinformationen aus spSchoolExtExam angemerged
// werden können:
keep ID_t exam datem datey tx28101 tx28103	

// Informationen aus spSchoolExtExam anspielen:
neps: merge 1:1 ID_t exam using spSchoolExtExam, keepusing(ts11300 ts11308) keep(master match) nogen
tempfile bildung
save `bildung'

// die Variablen aus den Datensätzen Basics und pTarget müssen nicht weiter vorbereitet,
// sondern können direkt gemerged werden

// alle Paneldaten zusammenspielen:
// ich benutze hier CohortProfile als zentrale Basis
neps: use CohortProfile, clear
keep ID_t wave tx8600m tx8600y tx80521

// Bildungsinfos
// m:1 merge, da Bildungsdaten nur pro Person vorliegen. Infos werden daher an ALLE Wellen
// als zeitkonstante Variablen angespielt)
merge m:1 ID_t using `bildung', assert(master match) nogenerate

// Basics: 
// m:1 merge, da Bildungsdaten nur per Person vorliegen. Infos werden daher an ALLE Wellen
// als zeitkonstante Variablen angespielt)
neps: merge m:1 ID_t using Basics, keepusing(tx29003 tx29064 tx29068) assert(master match) nogenerate

// pTarget
// 1:1 merge, da Inhalte aus pTarget wellenbasiert vorliegen
neps: merge 1:1 ID_t wave using pTarget, keepusing(t400500_g1 t400500_g3 t413500_v1 t514002 t514009 t515035 t700001 t70000y t724201 t725000 t731301_g1 t731301_g2 t731351_g2 t731401 t731402 t731404_v1 t731451 t731454_v1 t751001_g2) assert(master match) nogen

// Episodendaten
// hierfür muss anhand der tx8600my Variablen noch eine Interviewdatumsangabe zum
// korrekten mergen erstellt werden:
generate intdate=ym(tx8600y, tx8600m)
drop tx86*
// jetzt muss 1:1 über ID_t und intdate gemerged werden
// da derzeit aber auch noch Fälle in CohorProfile enthalten sind, die gar kein gültiges Interview
// in einer Welle abgeschlossen haben, müssen diese Zeilen vorher noch entfernt werden.

// sicherstellen, dass das Interviewdatum nur fehlt, wenn auch kein gültiges Interview vorliegt
assert missing(intdate) if tx80521 !=1
// bei gültigem Interview muss auch ein Interviewdatum vorliegen!!!	
assert !missing(intdate) if tx80521 ==1
// jetzt können alle Infos ohne Interviewdatum entfernt werden, weil das eh Nichtteilnehmer sind
drop if missing(intdate)		
drop tx80521

merge 1:m ID_t intdate using `Episodendaten', keep(master match) nogen

// Jetzt gibt es noch eine offene Frage:
// Derzeit befinden sich noch parallele Erwerbsepisoden innerhalb der Daten, dh. manche
// Personen haben bis zu 6 parallele Jobs. Um die Daten vernünftig analysieren zu können,
// müsste man jetzt noch überlegen, wie man diese Parallelität auf nur noch eine Information
// pro Person und Welle reduziert:
// Denkbar wären hier verschiedene Ansätze:
// (1) Summen- oder Mittelwertsbildung zB bei Variablen wie Einkommen, Arbeitszeit etc.
// (2) Selektion einer einzigen Erwerbsepisode und Auswahl anhand (a) höchstem Einkommen
//  oder (b) höchstem Arbeitszeitvolumen
// Das sollte man allerdings der Einfachheit halber schon oben bei der Aufbereitung der spEmp
// Daten integrieren...
duplicates report ID_t intdate
quietly : duplicates tag ID_t intdate , generate(dups)
tabulate dups

keep if dups ==0 // <-- oder very quick und very dirty (NICHT ZU EMPFEHLEN!!!)

Ich hoffe, damit ist dir ein bisschen gedient und du kannst das als Basis für deine weiteren Aufbereitungs- oder Analyseschrittte nutzen?
Bei weiteren Fragen jederzeit gerne melden!

Beste Grüße,
Benno

Hallo Benno,
vielen Dank für die ausführliche Antwort!

Mir ist aufgefallen, dass jetzt nach dem mergen noch manche Personen bis zu 6 Jobs haben, weil noch parallele Erwerbsepisoden innerhalb der Daten vorhanden sind.

Die Überlegung nun ist dies auf eine Information pro Person und Welle zu reduzieren. Entweder per Summen- oder Mittelwertsbildung von Einkommen oder Arbeitszeit, etc., oder Selektion einer einzigen Erwerbsperiode, die anhand des höchsten Einkommens oder höchsten Arbeitsvolumen ausgewählt werden soll.

Es soll jeweils am Ende der Periode, die angeschaut wird, die Erwerbsperiode genommen werden, in der sich die Person gerade befindet. Also, wenn die Zeiträume von 2010 bis 2015 und 2015 bis 2020 verwendet werden, wird das Einkommen und der Berufsstatus von 2010, 2015 und 2020 benötigt. Anschließend sollen dann die Daten verglichen werden.

Haben Sie eventuell eine Idee für ein mögliches weiteres Vorgehen?

Vielen Dank schon im Voraus!

Viele Grüße
Katharina

Liebe Katharina,

prinzipiell habe ich da viele Ideen, aber ich verstehe leider dein Ansinnen noch nicht ganz.
Es gibt Personen, die zB seit über 20 Jahren bei zwei verschiedenen Firmen angestellt sind und zudem noch nebenher selbständig tätig, d.h. hier laufen über den ganzen Zeitraum mehrere parallele Erwerbsepisoden ab. Und hier muss man eben verschiedene Entscheidungen treffen. Also du.
Wenn du weißt, was du wie analysieren willst, kann ich dir im Anschluss vielleicht ein paar Tipps geben, wie du den entsprechenden Analysedatensatz zusammenbaust…

Beste Grüße,
Benno

Lieber Benno,

ich arbeite gemeinsam mit Katharina an dem Projekt und antworte für uns. Vielen Dank für deine bisherige Hilfe auch von meiner Seite.
Wir wollen die parallelen Erwerbsepisoden eingrenzen, indem wir immer den Job berücksichtigen, in dem die meisten Stunden gearbeitet werden. Es wäre wunderbar, wenn du dafür Tipps für uns hättest.

Außerdem brauchen wir prinzipiell nur die Daten aus 2010 und 2020. Siehst du ein Problem darin, wenn wir alle Wellen bis auf die Welle 1 (weil dort viele Informationen zu Schulabschluss etc. vorhanden sind), Welle 2 (2010/2011) und Welle 12 (2020/2021) löschen? Wir bilden eine Variable als AV auf Basis der Variable ts23201_g4. Es soll darum gehen, zu überprüfen, ob Befragte den Weg aus der Überqualifizierung schaffen oder nicht. Wir vergleichen also, ob sie in Welle 2 überqualifiziert sind und ob sie in Welle 12 überqualifiziert sind.

Und wir bräuchten als UV noch die Info, ob der Beruf gewechselt wurde oder nicht. Wie kann man da am besten vorgehen? Sollen wir dafür eine Variable auf Basis von ts2312y_g1 bilden? Hast du da einen Tipp für uns?

Vielen Dank im Voraus und viele Grüße,
Julia

Liebe Julia,

dazu würde ich nach der bisherigen Aufbereitung einfach gruppiert nach Person und Interviewzeitpunkt das Maximum der tatsächlichen Arbeitszeit (ts23223_g1) berechnen:
Beispielsweise über:
bysort ID_t intdate: egen maxjobtime = max(ts23223_g1)
Dummerweise kann man damit jedoch immer noch nicht alle parallelen Erwerbsepisoden direkt eindeutig selektieren, weil es auch Episoden gibt, in denen wir kein Maximum haben, Personen mit gleichem Zeitumfang arbeiten usw usw. Also müsst ihr da eh nochmal ein wenig genauer in die Daten gucken und euch plausible Selektionskriterien für die weiteren Parallelitäten überlegen.

Wenn ihr wirklich nur die Informationen aus W2 und W12 für eure Analysen benutzen wollt, dann spricht meiner Ansicht nach nichts dagegen, warum man dann die unbenutzte Information in den Daten halten sollte. Ob das in eurem Analyseszenario letztlich Sinn macht, werdet ihr euch ja überlegt haben.

In einer idealtypischen Befragungswelt wurde immer ein neuer Spell innerhalb der Episodendaten begonnen, wenn etwas geendet und etwas neues begonnen hat. Also wenn eine Person einen neuen Job hat, sollte sie auch eine neue Erwerbsepisode haben. Insofern müsstet ihr euch nur einen Indikator bilden, ob in dem Zeitfenster, das euch interessiert, die Person am Ende eine andere Spellnummer hat als am Anfang.
Allerdings kommen mit da noch ein paar Anschlussfragen: Was macht ihr aber, wenn die Person von einem Arbeitgeber zu einem anderen gewechselt ist und immer noch den vollkommen identischen Job ausübt? Ist das dann in eurem Sinne ein Jobwechsel? Was macht ihr, wenn eine Person mehrere parallele Jobs hat und nur einen davon über die Zeit wechselt, den anderen aber behält? Ich schätze, da gibt es noch ein paar Überlegungen, die man anstellen müsste, bevor man die Daten da sinnvoll aufbereiten kann. Aber ich bin mir sicher, dass ihr das hinbekommt!

Beste Grüße,
Benno