Automatisierung von Fallauswahl

Fragen und Diskussionen rund um die Arbeit mit SPSS. Für allgemeine Statistik-Themen, die nicht mit SPSS zusammenhängen, bitte das Statistik-Forum nutzen.
Antworten
Michajan
Beiträge: 10
Registriert: 21.02.2011, 10:09

Automatisierung von Fallauswahl

Beitrag von Michajan »

Liebe Freunde.
Von einer Messfläche im Wald habe ich Messdaten in drei Variablen bekommen: CODE_VARIABLE, DATE and DAILY_MEAN. Die erste Variable kann zum Beispiel Lufttemperatur oder Regenmenge sein. Ich möchte diese Datei jetzt aufspalten in Dateien, in denen jeweils nur die Daten eines Typs von CODE_VARIABLE ist, also eine Datei mit allen Luifttemperatur-Daten zum Beispiel und speichern.
Der einfache Weg, das zu machen, ist es in der Datei zu gucken, welche verschiedenen CODE_VARIABLEs es gibt und dann für jede dieser eine SELECT-Anweisung auszuführen.
Ich kann ein Makro schreiben und es für alle unterschiedlichen CODE_VARIABLEs ausführen. Wenn ich den Prozess automatisieren möchte, habe ich das Problem, dass ich vorher nicht weiß, welche unterschiedlichen Inhalte die Variable CODE_VARIABLE hat.

Ich erhalte die Information, wenn ich die Ausgangsdatei aggregiere, zum Beipiel
*AGGREGATE
/OUTFILE='Variable_codes'
/BREAK=CODE_VARIABLE
/DATE_min=MIN(DATE).

Aber wie kann ich SPSS sagen, er möge doch bitte das Makro für alle unterschiedlichen Inhalte der Variable CODE_VARIABLE genau einmal ausführen?

Ich habe KEINE Idee. Ihr vielleicht?
Das wäre eine echt elegante Lösung.

Vielen Dank an alle Helferlein.

Michajan
drfg2008
Beiträge: 2391
Registriert: 06.02.2011, 19:58

re:

Beitrag von drfg2008 »

Die Frage ist mir nicht klar.

Und besser, du gibst einmal die Struktur der Datei genau (!) an.

Hier schon das erste Problem:

[quote]Die erste Variable kann zum Beispiel Lufttemperatur oder Regenmenge sein.[/quote]

Ist hier bereits der Meßwert enthalten, oder handelt es sich nur um die Kategorie 'Lufttemperatur' oder 'Regenmenge' und der eigentliche Meßwert findet sich dann in einer anderen Variablen?

[quote]Der einfache Weg, das zu machen, ist es in der Datei zu gucken, welche verschiedenen CODE_VARIABLEs es gibt und dann für jede dieser eine SELECT-Anweisung auszuführen. [/quote]

Was meinst du damit? Gibt es die Varialbe CODE_VARIABLE 1 CODE_VARIABLE 2 CODE_VARIABLE 3, etc. ?


Wenn du eine dynamische Generierung einer Datei hast, bei der SPSS sozusagen erst einmal selbst sehen muss, wie viel und welche Variablen berechnet werden können, kommt eigentlich Python in Frage. Python ist in der Lage, Variablen dynamisch auszulesen. Das geht so:


[code]BEGIN PROGRAM.
import spss
spss.Submit("GET FILE='C:/<path>/dateiname.sav'.")
catlist=[]
scalist=[]
for i in range(spss.GetVariableCount()):
varName=spss.GetVariableName(i)
if spss.GetVariableMeasurementLevel(i) in ['nominal', 'ordinal']:
catlist.append(varName)
else:
scalist.append(varName)
if len(catlist):
categoricalVars = " ".join(catlist)
spss.SetMacroValue("!catvars", categoricalVars)
if len(scalist):
scaleVars = " ".join(scalist)
spss.SetMacroValue("!scavars", scaleVars)
END PROGRAM.
FREQUENCIES !catvars.
DESCRIPTIVES !scavars.[/code]

Dazu muss Python installiert sein, auch das Pyton Plugin. Außerdem darauf achten, dass die Einschübe korrekt sind, weil Python keine {} Klammern verwendet und daher im if-else Bereich sonst Fehler meldet. Die Einschübe gehen hier wahrscheinlich verloren.

Wenn es allerdings um dynamisch erzeugte 'Gruppen' einer Variablen geht, wäre das eine andere Frage. Dann müssten die einzelnen 'Wertelables' ausgelesen werden und für jede einzelne die Berechnungen durchgeführt werden (?)

Generell ist die Verwendung von Python hier sicherlich nützlich. Denn ( Python kann dynamisch Abfragen generieren. Beispiele dafür findet man auf der IBM Website (ProgDataMgmt_SPSS17.pdf)

Gruß
Michajan
Beiträge: 10
Registriert: 21.02.2011, 10:09

Beitrag von Michajan »

Vielen Dank für dein Engagement. Python ist sicher eine Lösung.
Später wollen andere Leute aber sicher nachvollziehen, was ich da gemacht habe, um meine Resultate zu produzieren und deshalb möchte ich nicht die Sprache ändern.
Ich gebe mal hier ein Beispiel wie so eine Datei aussieht. also wir haben die drei Variablen CODE_VARIABLE, DATE und DAILY_MEAN.
CODE_VARIABLE ist ein String mit der Länge 2, DATE ist ein Datum (wer hätte es gedacht) und DAILY_MEAN beinhaltet den Messwert. Zum Beispiel:
CODE_VARIABLE DATE DAILY_MEAN
AT 1.1.2000 5
AT 2.1.2000 6
AT 3.1.2000 7
AT 4.1.2000 8
AT 5.1.2000 9
RH 1.12.2002 50
RH 2.12.2002 60
RH 3.12.2002 40
RH 4.12.2002 15

und ich möchte als Resultat
CODE_VARIABLE DATE DAILY_MEAN
AT 1.1.2000 5
AT 2.1.2000 6
AT 3.1.2000 7
AT 4.1.2000 8
AT 5.1.2000 9
und
CODE_VARIABLE DATE DAILY_MEAN
RH 1.12.2002 50
RH 2.12.2002 60
RH 3.12.2002 40
RH 4.12.2002 15

also eigentlich ganz einfach, nur dass ich das automatisieren möchte, am liebsten in einer Schleife.
Ich habe mehr Erfahrung in C, dort würde ich alle unterschiedlichen Inhalte von CODE_VARIABLE als Elemente in einen Array packen und dann in einer Schleife nach dem inhalt eines jeden Elements filtern und das Ergebnis abspeichern.
For( i=0;i<arraylength-1;i++)
{
DATASET ACTIVATE all.
SELECT IF CODE_VARIABLE=array.
EXECUTE.
SAVE OUTFILE=blablub.*vielleicht noch einen Namen aus CODE_VARIABLE generieren
}
in unserem Beispiel mit den Elementen
array[0]='AT'
array[1]='RH'

Vielleicht kommt da sowas wie SPLIT FILE in Frage. Aber da fehlt mir die Erfahrung.
drfg2008
Beiträge: 2391
Registriert: 06.02.2011, 19:58

re

Beitrag von drfg2008 »

Python ist Bestandteil von SPSS (ab glaube V19 muss sogar nicht einmal ein Plugin installiert sein) und findet sich auch direkt im SPSS-Syntax Code. Wird also auch dokumentiert und ist sehr einfach (bei C-Vorkenntnissen)

Python geht genau so vor wie dein C-Beispiel (nur ohne {}). Siehe erste Antwort. Python ist C sehr ähnlich.

Jetzt wäre noch die Frage, ob die Anzahl der Kategorien in CODE_VARIABLE dynamisch ist (wovon ich ausgehe) oder nicht. Falls die alle bekannt sind, wäre das ja kein Problem: mit select.

Mit aggregate hingegen wird eine Zusammenfassung (Aggregierungsfunktion) nach Gruppe berechnet (bsw. der Mean). Aber das soll's ja wohl nicht sein.

Ohne Python gäbe es vielleicht noch eine (gewagte) Lösung: Über automatisches Recodieren werden die Strings in CODE_VARIABLE in Zahlen codiert. Über diese lassen sich dann per Makro-Schleife die Dateien splitten. Denn ich kann ja Zahlen vorgeben: 1 - bis x. Wobei x eine sehr große Zahl ist, die nicht erreicht wird. Aber auch hier das Problem: Es ist nicht im Voraus bekannt, wie viele Gruppen entstehen. Und ich weiß auch nicht, wie die Fehler dann abgefangen werden falls weniger Gruppen entstehen als in der Schleife vorgegeben (vielleicht entsteht nur eine Fehlermeldung, das Programm läuft aber bis Ende weiter). Nicht elegant, könnte aber gehen.

Ein Blick in Python wäre sinnvoll.

Gruß
Michajan
Beiträge: 10
Registriert: 21.02.2011, 10:09

Beitrag von Michajan »

OK, ich wusste nicht, dass Python in SPSS eingebaut ist. Wieder was gelernt.
Die Anzahl der Kategorien in CODE_VARIABLE ist variabel, aber es gibt maximal zehn oder so. Ich gucke mir das mit dem Python noch mal genauer an.
Vielen Dank auf jeden Fall.

Michajan
drfg2008
Beiträge: 2391
Registriert: 06.02.2011, 19:58

re

Beitrag von drfg2008 »

Hier noch ein Zusatz:

laut IBM gibt es dafür keine direkte Methode in phyton: "no prepackaged api for this" (siehe Anhang). Wenn ich das richtig verstanden habe.


Allerdings bietet sich folgende Möglichkeit:

1. über 'aggregate' die einzelnen Gruppen auslesen und damit dynamisch identifizieren
2. über den python Befehl spss.GetCaseCount() die Anzahl der Fälle auslesen. Das ist damit auch die Anzahl der Gruppen.
3. Die Zahl lässt sich innerhalb des SPSS Codes in ein Makro einlesen und dort über eine Schleife die jeweiligen Prozeduren berechnen (oder select).

Etwas kompliziert.

Gruß


Anhang:

In order to get the number of distinct values of a variable, you would have to pass the data. It could be determined using AGGREGATE, for example, but there is no prepackaged api for this.

Use a dataset rather than file with AGGREGATE so that you do not have to worry about directories.
Then activate that dataset and use spss.GetCaseCount() to find the size.


J P
Senior Software Engineer, IBM
drfg2008
Beiträge: 2391
Registriert: 06.02.2011, 19:58

re

Beitrag von drfg2008 »

Hier ist übrigens meine Lösung. Es gibt noch eine Lösung von IBM vom 15.Feb. 2010 über ein Extension command [1]

Einige Voraussetzungen:
Python muss installiert sein, ebenso Plugin (falls ältere Version)
relevante Variablen: gruppe = Splitvariable, FILE_SPLITTEN.sav = ursprüngl. Datensatz

Code: Alles auswählen


*--------------------------------------------.


*------------------------ generate Data (start) ------------------------------.



input program.
loop a =1 to 100000 by 1.
end case.
end loop. 
end file.
end input program.
exe.


comp	gruppe=RV.BINOM(10,0.5).
COMP av_1=RV.NORMAL(1,10).
COMP av_2=RV.NORMAL(1,10).
COMP av_3=RV.NORMAL(1,10).
COMP av_4=RV.NORMAL(1,10).
EXECUTE .


SAVE OUTFILE='C:\<path>\FILE_SPLITTEN.sav'.

*------------------------------ End: generate Data --.

*------------ Start-----------------.


GET  FILE='C:\<path>\FILE_SPLITTEN.sav'.
DATASET NAME DatenSet1 WINDOW=FRONT.

AUTORECODE VARIABLES=gruppe 
  /INTO gruppe_codiert
  /PRINT.

DATASET DECLARE anzahl_gruppen.
AGGREGATE
  /OUTFILE='anzahl_gruppen'
  /BREAK=gruppe
  /N_BREAK=N.

DATASET ACTIVATE anzahl_gruppen.

BEGIN PROGRAM.
import spss
FileGROUPS=spss.GetCaseCount()
spss.Submit("DATASET ACTIVATE DatenSet1.")  

for i in range(FileGROUPS):
                                       spss.Submit("temporary.")                                              
                                       spss.Submit(" SELECT IF gruppe_codiert = " +str(i+1) +".") 
                                       spss.Submit("SAVE OUTFILE='C:/<path>/gruppe_ " +str( i+1) + ".sav'")

END PROGRAM.












[1] erster Artikel oben:

https://www.ibm.com/developerworks/myde ... 02?lang=en
Michajan
Beiträge: 10
Registriert: 21.02.2011, 10:09

Beitrag von Michajan »

Hey, du kennst dich echt aus.
Also Python schreibt den Code für SPSS.
Ich würde es gerne verstehen, daher ein paar Fragen dazu.
1: Sehe ich das richtig, dass ich in meinem speziellen Fall den ersten Teil des Codes (=generate Data (start)) nicht brauche, weil ich ja schon eigene Daten habe?
2:Warum kann man "end case" und "end file" schreiben, wenn man nie zuvor den Befehl "case" oder "file" angefangen hat?
3: Was bedeutet RV. ? Ist das ein Befehl für ein Unterprogramm?
4: Weiter unten steht
spss.Submit(" SELECT IF gruppe_codiert = " +str(i+1) +".") .
Woher weiß Python, dass es die Fälle der aggregierten Datei in str packen soll? Ich sehe nur, dass die Anzahl der Fälle gezählt wird und in FileGROUPS geschrieben wird.
Vielen Dank nochmals.
Michajan
drfg2008
Beiträge: 2391
Registriert: 06.02.2011, 19:58

re

Beitrag von drfg2008 »

Hallo Michajan,

ich schreibe die Antworten einfach mal direkt in den Text:


Also Python schreibt den Code für SPSS.
Nee, nee. Den schreibe ich schon selbst (Scherz).
Sobald über Begin Programm und End Programm ein externes Programm gestartet wird (R, .Net oder eben Python) befinde ich mich in diesem Programm und nicht mehr in SPSS Syntax. Also muss Python sozusagen als Mittler dem SPSS die Befehle weiterreichen über spss.submit. Das ist -sage ich mal- eine 'Funktion' (objektorientierte Programmierung- Objekt Methode müsste das sein. Kennst dich da sicher besser aus als C-Programmierer). Diese ist von SPSS gebastelt und kann nur so fertig genutzt werden, indem Argumente eingegeben werden.

1: Sehe ich das richtig, dass ich in meinem speziellen Fall den ersten Teil des Codes (=generate Data (start)) nicht brauche, weil ich ja schon eigene Daten habe?
Richtig.


2:Warum kann man "end case" und "end file" schreiben, wenn man nie zuvor den Befehl "case" oder "file" angefangen hat?

Gute Frage. Müsste IBM beantworten. Die Syntax richtet(e) sich ursprünglich ja nicht unbedingt an C-Programmierer, sondern an Personen, die sagen wir mal etwas 'liberaler' programmieren. Das könnte der Grund dafür sein. Die Hypothese müßte aber erst getestet werden ;-) In HTML funktioniert ja auch so vieles, was eigentlich nicht geht.

3: Was bedeutet RV. ? Ist das ein Befehl für ein Unterprogramm?
OK, das gehört natürlich nicht mehr zur Lösung. Ich generiere einfach nur Zufallsvariablen (RV= Random Variable), um einen Datensatz zu generieren.

4: Weiter unten steht
spss.Submit(" SELECT IF gruppe_codiert = " +str(i+1) +".") .
Woher weiß Python, dass es die Fälle der aggregierten Datei in str packen soll? Ich sehe nur, dass die Anzahl der Fälle gezählt wird und in FileGROUPS geschrieben wird.
Nee, nee. +str(i+1) sind zwei verschiedene Dinge. Python verkettet einfach mit dem + Zeichen. Das ist sehr gewöhnungsbedürftig. Die Python-Erfinder machen alles sehr sparsam [1]. Um eine Zahl mit einem String verketten zu können, muss die Zahl in einen String gewandelt werden. Denn Python kennt ja keine Variablendefinitionen wie etwa in Java oder C (am Anfang des Codes). Python entscheidet während der Laufzeit dann selbst, welcher Typ gewählt wird. Damit wäre in diesem Fall ein Konflikt verbunden.

SPSS soll lediglich folgenden Befehl über alle Gruppen zusammenketten:
SELECT IF gruppe_codiert = 1.
SELECT IF gruppe_codiert = 2.
SELECT IF gruppe_codiert = 3. usw

Die Anzahl der Gruppen wird in

Code: Alles auswählen

FileGROUPS=spss.GetCaseCount()
gezählt.

Wichtig ist das TEMPORARY. Nur so können die einzelnen "Dateien" offen gehalten werden und die nicht-selektierten Fälle werden nur vorübergehend gelöscht. Damit ist ein sehr starker Geschwindigkeitsvorteil verbunden, weil die Dateien nicht ständig geöffnet und geschlossen werden müssen.


Gruss


[1] hier im Original auf Youtube

http://www.youtube.com/watch?v=ujkzfC2lebA
Michajan
Beiträge: 10
Registriert: 21.02.2011, 10:09

Es geht auch ohne Python

Beitrag von Michajan »

Inzwischen kenne ich mich schon besser aus mit SPSS und ich habe eine Lösung ohne Python gefunden.
Wenn ich die Datei nach den unterschiedlichen Fälle aggregiere, bleibt für jeden Fall, den ich auswählen und einzeln abspeichern möchte, genau ein Fall übrig.
Dann wende ich ein paar String-Operationen an und erzeuge mir innerhalb dieses Datenblattes eine String-Varible, die pro Zeile einen Makroaufruf mit dem auszuwählenden Fall als Argument enthält.
Dann kommt der Clou an der Sache. Ich exportiere den Inhalt des Datenblattes als Text und hänge die Endung sps an. Mit einem INSERT-Befehl wird die soeben generierte sps-Datei eingelesen und die dynamisch generierten Makroaufrufe weren ausgeführt.
Klappt wunderbar!
Anzeige:Statistik und SPSS: Die besten Bücher
Als Buch oder E-Book - Jetzt bestellen
spss datenanalyse
SPSS - Moderne Datenanalyse - Jetzt bestellen!
statistik datenanalyse
Statistik - Der Weg zur Datenanalyse - Jetzt bestellen!
Antworten