首页 文章

如何将Mata值写入txt文件?

提问于
浏览
0

我正在使用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 回答

  • 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中,宏只扩展一次 - 编译Mata函数或语句时 . 如果再次运行该函数,则宏不会再次展开,即使其值已更改 .

    换句话说,首先编译Mata代码,在此期间所有宏立即被扩展一次,然后执行编译的代码 . 执行的代码是否会更改宏的值无关紧要,因为宏将永远不再在该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'` 不是't set when the for-loop is first compiled, they are immediately expanded away. It'与您输入的完全相同:

    st_local("j_ll",strofreal(j))
    st_local("filenumber_ll",filenumber)
    
    stata(`" display "Filenumber=" "')
    stata(`" display "J=" "')
    

    只有在宏扩展并且for循环编译后才进行循环运行 .

    如果这没有意义,比尔古尔德在文章中更深入 .

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

    您仍然可以访问宏's changing value in Mata, you just can' t使用 ``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 ..."')替换为Matadisplay()` 函数:

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

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

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

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

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

相关问题