2017-06-23 117 views
0

我正在使用Stata 14 SE。我有相当长的脚本,利用嵌套循环来生成一些蒙特卡罗数据。在某一点上,循环可能会失败,然后我想要它将一些结果写入一个txt文件,以便我知道它在哪一点失败。如何将Mata值写入txt文件?

为此,我使用以下代码。这部分是在几个其他循环内调用的函数的几个循环内。

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 "') 
} 

而且它在Stata返回以下输出:

Price Iteration Failed 
001 
2 
Filenumber= 
J= 

正如你所看到的Stata看到“filenumber_ll”和“j_ll”的价值,但拒绝显示它并写入文件。

顺便说一句我也是在一个独立的代码尝试这些命令:

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 

,然后我收到这样的输出:

filenumber 
Filenumber=filenumber 
J=5 

所以它似乎工作。

我不明白为什么它在独立文件中工作,但不在循环中。任何帮助?

回答

2

这是怎么发生的?

比尔古尔德写了一篇非常有用的文章,名为Mata Matters: Macros。我建议阅读整个事情,但我会注意到一个重要的部分是宏在Stata和Mata中的扩展方式不同。

在Stata,在for循环宏的值可以用循环的每次迭代改变:仅仅一次—

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' 
} 

然而,在马塔,宏膨胀时马塔功能或语句被编译。如果函数再次运行,即使宏的值已更改,宏也不会再次扩展。

换句话说,第一马塔代码被编译,在此期间所有的宏立即被展开正好一次,然后经编译的代码被执行。执行的代码是否更改宏的值并不重要,因为宏不会再在该Mata代码中进行扩展。

在你的for循环的情况下,就好像Mata在循环中搜索任何宏,用它们的值替换它们,然后只运行for循环。所得到的代码与您只用宏的值开始编写for循环时没有任何实际的宏一样。

这意味着,因为您已将第一个if包装在for循环中,所以在循环执行之前,其中的宏将立即展开。你if块包括这些行:

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

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

如果`j_ll'`filenumber'未设置时for循环首先编译,它们立即被展开了。它与您键入的内容完全相同:

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

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

只有宏一次扩展并且for循环编译为循环运行。

如果这没有意义,比尔古尔德会在文章中进一步深入。

这对您的代码意味着什么?

您仍然可以访问Mata中一个宏的变化值,但您不能使用`localname'语法来执行此操作。相反,使用st_local()。你的最后两行会变成:

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

如果您需要访问一个宏观的变化值或马塔代码之后的宏设定的值被编译,使用st_local()`localname'通常保留用于在编译Mata代码之前访问宏集的不变值。

现在,这两行并不完全是世界上最可读的代码。为了简化,只需要使用已存在的马塔变量:

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

更妙的是,与马塔display()函数替换stata(`"display ..."')

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

同样,使用fopen()和其他马塔文件的功能,而不是stata(`"file ..."')。或者,不要使用文件,只需将您需要的值保存在代码末尾显示的Mata变量中,或者使用_error()来引发错误并立即停止代码。

它为什么以交互方式工作?

您的代码以交互方式工作,因为交互式语句不会包含在if块,for循环或函数中,并且会被编译,然后立即执行。它们不是一次编译完成,而是作为一个块执行。

这意味着改变宏值的早期行会影响后面的行。当这些行被编译在一起时情况并非如此。

+0

马特,谢谢你的非常详细的答案。我现在明白它好多了。同时我将循环内容放在另一个do-file中,然后在循环中调用它。在这种情况下,宏似乎会随着每次迭代而更新,并做我想做的事情。但是你的解决方案更加优雅。再次感谢你!我花了好几天的时间试图找出答案。 – Odysseus56