2017-06-23 4 views
0

Ich benutze Stata 14 SE. Ich habe ein ziemlich langes Skript, das verschachtelte Schleifen verwendet, um einige Monte-Carlo-Daten zu erzeugen. Irgendwann kann eine Schleife ausfallen und dann möchte ich einige Ergebnisse in eine txt-Datei schreiben, so dass ich weiß, an welchem ​​Punkt es gescheitert ist.Wie kann ich Mata-Wert in eine TXT-Datei schreiben?

Dafür verwende ich den folgenden Code. Dieser Teil befindet sich innerhalb mehrerer Schleifen einer Funktion, die in einigen anderen Schleifen aufgerufen wird.

if(f_iterations == f_it_max - 1) { 
    stata(`" display "Price Iteration Failed" "') 

    st_local("filenumber_ll",filenumber) 
    st_local("j_ll",strofreal(j)) 

    st_local("filenumber_ll") 
    st_local("j_ll") 

    stata(`" display "Filenumber=`filenumber_ll'" "') 
    stata(`" display "J=`j_ll'" "') 

    stata(`" file write myfile4 `" Failure in file `filenumber_ll', market `j_ll' "' _n "') 
} 

Und es gibt die folgende Ausgabe in Stata:

Price Iteration Failed 
001 
2 
Filenumber= 
J= 

Wie Sie sehen können Stata den Wert von „filenumber_ll“ sieht und „j_ll“ weigert sich aber, um es anzuzeigen und zu schreiben einzureichen.

Übrigens habe ich versucht, diese Befehle auch in einem eigenständigen Code:

mata 

j=5 

filenumber="filenumber" 
filenumber 

st_local("j_ll",strofreal(j)) 
st_local("filenumber_ll",filenumber) 

stata(`" display "Filenumber=`filenumber_ll'" "') 
stata(`" display "J=`j_ll'" "') 

stata(`" file open myfile25 using `"!test.txt"', write replace "') 
stata(`" file write myfile25 `"Failure in file `filenumber_ll', market `j_ll'"' _n "') 
stata(`" file close myfile25 "') 

end 

und dann erhalte ich diese Ausgabe:

filenumber 
Filenumber=filenumber 
J=5 

So scheint es zu funktionieren.

Ich verstehe nicht, warum es in einer eigenständigen Datei funktioniert, aber nicht innerhalb einer Schleife. Irgendeine Hilfe?

Antwort

2

Warum passiert das?

Bill Gould hat einen sehr nützlichen Artikel dazu geschrieben, der Mata Matters: Macros genannt wird. Ich empfehle, das Ganze zu lesen, aber ich stelle fest, dass ein wichtiger Teil darin besteht, dass Makros in Stata und Mata unterschiedlich expandiert sind.

In Stata, der Wert eines Makro in einer for-Schleife kann mit jeder Iteration der Schleife ändern:

forvalues i = 1/100 { 
    * The for-loop has only one line of code and one macro, 
    * but the macro expands to 100 different values over 
    * the course of the loop. 
    display `i' 
} 

jedoch in Mata, ein Makro erweitert wird nur einmal — wenn die Mata Funktion oder Anweisung wird kompiliert. Wenn die Funktion erneut ausgeführt wird, wird das Makro nicht erneut erweitert, auch wenn sich sein Wert geändert hat.

Mit anderen Worten, erste der Mata-Code kompiliert wird, bei der alle Makros sofort erweitert werden genau einmal, dann der kompilierte Code ausgeführt wird. Es spielt keine Rolle, ob der ausgeführte Code die Werte der Makros ändert, da die Makros in diesem Mata-Code nie wieder erweitert werden.

Im Fall Ihrer for-Schleife ist es so, als ob Mata die Schleife nach irgendwelchen Makros durchsucht, sie durch ihre Werte ersetzt und erst dann die for-Schleife ausführt. Der resultierende Code ist derselbe wie wenn Sie die for-Schleife nur mit den Werten der Makros geschrieben hätten, ohne dass sie tatsächlich Makros hätten.

Dies bedeutet, dass, da Sie das erste if in einer For-Schleife gewickelt haben, die darin enthaltenen Makros sofort erweitert werden, bevor die Schleife ausgeführt wird. Ihr if Block enthält die folgenden Zeilen:

st_local("j_ll",strofreal(j)) 
st_local("filenumber_ll",filenumber) 

stata(`" display "Filenumber=`filenumber_ll'" "') 
stata(`" display "J=`j_ll'" "') 

Wenn `j_ll' und `filenumber' nicht gesetzt ist, wenn die for-Schleife zuerst kompiliert wird, werden sie sofort weg erweitert.Es ist genau das gleiche, als wenn Sie eingegeben hatte:

st_local("j_ll",strofreal(j)) 
st_local("filenumber_ll",filenumber) 

stata(`" display "Filenumber=" "') 
stata(`" display "J=" "') 

Erst wenn die Makros werden erweitert und die for-Schleife kompiliert ist die Schleifendurchlauf.

Wenn das keinen Sinn ergibt, geht Bill Gould in dem Artikel mehr in die Tiefe.

Was bedeutet das für Ihren Code?

Sie noch ein Makro des Änderungswert in Mata zugreifen können, kann man einfach nicht die `localname' Syntax verwenden, dies zu tun. Verwenden Sie stattdessen st_local(). Ihre letzten beiden Zeilen würde:

stata(`" display "Filenumber="' + st_local("filenumber_ll") + `"" "') 
stata(`" display "J="' + st_local("j_ll") + `"" "') 

Wenn Sie eine einzelne Makros Änderungswert oder den Wert eines Makro-Reihe nach dem Mata-Code für den Zugriff kompiliert, verwenden st_local(). `localname' ist normalerweise für den Zugriff auf den unveränderlichen Wert eines Makrosatzes reserviert, bevor der Mata-Code kompiliert wird.

Jetzt sind diese beiden Zeilen nicht gerade der weltweit lesbarste Code. Zur Vereinfachung, benutzen Sie einfach die Mata-Variablen, die bereits vorhanden sind:

stata(`" display "Filenumber="' + filenumber + `"" "') 
stata(`" display "J="' + strofreal(j) + `"" "') 

Besser noch, ersetzen stata(`"display ..."') mit der Mata display() Funktion:

display("Filenumber=" + filenumber) 
display("J=" + strofreal(j)) 

Ähnlich fopen() verwenden und die anderen Mata Dateifunktionen statt stata(`"file ..."'). Oder, anstatt eine Datei zu verwenden, speichern Sie einfach die Werte, die Sie in Mata-Variablen benötigen, die Sie am Ende des Codes anzeigen, oder verwenden Sie _error(), um einen Fehler auszulösen und den Code sofort zu stoppen.

Warum hat es interaktiv funktioniert?

Ihr Code funktioniert interaktiv, weil die interaktiven Aussagen nicht umgebrochen werden in einem if-Block, for-Schleife oder eine Funktion und kompiliert werden dann sofort ausgeführt, einer nach dem anderen. Sie werden nicht auf einmal kompiliert und als Block ausgeführt.

Dies bedeutet, dass die früheren Zeilen, die die Werte der Makros ändern, die späteren Zeilen beeinflussen. Das ist nicht der Fall, wenn die Zeilen zusammen kompiliert werden.

+0

Matt, danke für die sehr detaillierte Antwort. Ich verstehe es jetzt viel besser. Inzwischen legte ich den Inhalt der Schleife innerhalb einer anderen do-Datei und nenne es dann innerhalb der Schleife. In diesem Fall scheinen die Makros mit jeder Iteration aktualisiert zu werden und tun, was ich wollte. Aber deine Lösung ist viel eleganter. Danke nochmal! Ich habe mehrere Tage damit verbracht, es herauszufinden. – Odysseus56

Verwandte Themen