如何将Mata值写入txt文件?

时间:2017-06-23 22:43:17

标签: stata

我正在使用Stata 14 SE。我有相当长的脚本,利用嵌套循环生成一些蒙特卡罗数据。在某些时候循环可能会失败,然后我想将它写入一个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

所以它似乎有效。

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

1 个答案:

答案 0 :(得分:2)

为什么会这样?

Bill Gould写了一篇非常有用的文章,名为 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中,宏只扩展一次 - 编译Mata函数或语句时。如果再次运行该函数,则宏不会再次展开,即使其值已更改。

换句话说,首先编译Mata代码,在此期间所有宏都会立即展开一次,然后执行编译后的代码。执行的代码是否会更改宏的值并不重要,因为宏将永远不会再在该Mata代码中进行扩展。

对于for循环,就好像Mata在循环中搜索任何宏,用它们的值替换它们,然后才运行for循环。生成的代码与您编写只包含宏开头的for循环的代码相同,没有任何实际的宏。

这意味着,由于您在for循环中包含了第一个if,因此在执行循环之前,其中的宏会立即展开。您的if块包含以下行:

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

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

如果首次编译for循环时未设置`j_ll'`filenumber',则会立即将其展开。它与您键入的内容完全相同:

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") + `"" "')

如果在编译Mata代码后需要访问单个宏的更改值或宏集的值,请使用st_local()`localname'通常保留用于在编译Mata代码之前访问宏集的不变值。

现在,这两行并不是世界上最易读的代码。要简化它,只需使用已存在的Mata变量:

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

更好的是,将stata(`"display ..."')替换为Mata display()函数:

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

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

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

您的代码以交互方式工作,因为交互式语句不包含在if-block,for-loop或函数中,然后编译然后立即执行,一个接一个。它们不是一次编译而是作为一个块执行。

这意味着更改宏值的早期行会影响后面的行。线条编译在一起时并非如此。