在Mata中使用put_formula()导出相对Excel引用

时间:2019-02-07 21:02:43

标签: stata

我正在将很多字符串从Stata导出到Excel。

对于# A tibble: 3 x 3 # Groups: id [1] id year value <int> <int> <int> 1 2 1998 90 2 2 1999 91 3 2 2002 92 行中的每一列,每行中都有不同的字符串,我需要检查每个字符串/单元格的长度。我可以使用3000+函数在Stata中做到这一点,但是我需要能够打开Excel文件,编辑给定的字符串,并在Excel中自动更新长度。

使用length()命令或mata的putexcel函数似乎应该很简单,但是运行时间太长了。

从根本上讲,我的问题是关于一次在put_formula()中建立许多相对引用(例如=LEN(A1)),而不是一次建立一个。

看到下面的代码后,这可能更有意义:

mata

运行最后一行时,出现错误:

mata: b = xl()
mata: b.create_book("Formula_Test", "Formula_Test", "xlsx")
mata: b.load_book("Formula_Test") 

*Put some strings in column 1
mata: b.put_string(1, 1, "asfas")
mata: b.put_string(2, 1, "sfhds")
mata: b.put_string(3, 1, "qwrq")
mata: b.put_string(4, 1, "dgsdgsdgsdgs")

*Formula - export one-at-a-time
    *This works, but is slow
foreach i of numlist 1/4{
    mata: b.put_formula(`i', 2, "LEN(A`i')")
}

*Formula - export all at once with relative reference
    *This would be faster, but throws error
mata: b.put_formula((1,4), 3, "LEN(INDIRECT("C[-2]",FALSE))")

是否有一种有效的方法可以使用invalid expression r(3000); 以及相对引用来编写整个Excel公式的列或行?

2 个答案:

答案 0 :(得分:2)

mata函数put_formula()仅接受行和列的标量。请注意,您还需要在其字符串矩阵参数中使用复合双引号。

mata中循环总是比在Stata中更快:

mata:
for (i = 1; i <= 4; i++) {
    b.put_formula(i, 2, `"LEN(INDIRECT("C[-2]",FALSE))"')
}
end

尽管如此,尽管必须使用标量作为put_formula()中行和列的参数,但实际上并不需要循环。这是因为可以将常量的字符串矩阵J指定为最终参数。

实际上,以下内容在几秒钟内完成了相同的操作

mata:
k = J(3000, 1, `"LEN(INDIRECT("C[-1]",FALSE))"')
b.put_formula(1, 2, k)
end

通过这种方式,矩阵J[3000,1]在电子表格的单元格B1中写入了一次。由于它具有3000行,因此自然可以扩展到B3000的所有单元格。

答案 1 :(得分:1)

此答案是次要的,但对某人可能有用。

问题代码的效率低下–遍历一个numlist并将该公式一次写入一个单元格中–一定程度上是由于使用了Stata循环(如Pearly Spencer所指出和纠正的)。但是更大的问题是,当示例从4个单元扩展到数千个时,mata必须编写单个单元的次数。

如果可以避免单独循环和写入多个单元格,则在大多数应用程序中,使用-putexcel-或mata的b.put_formula的速度不会出现显着差异。如果您要在单元格的单个列,行或矩阵中写入单元格,并且可以一次写入所有单元格,则任何一种选择都会很快。 -putexcel-示例:

*A -putexcel- example
mata: b.create_book("Formula_Test", "Formula_Test", "xlsx")    
putexcel set "Formula_Test", sheet("Formula_Test") modify
putexcel B1:B30000 = formula(`" =LEN(INDIRECT("C[-1]",FALSE)) "')

对于单列中的30,000个单元格,-putexcel-用了37秒。

在mata中使用Pearly Spencer的J矩阵方法耗时36秒。

重要的一点是:如果您要向多个单元格编写公式,请尝试将其合并为可作为矩阵一起编写的块,而不是遍历所有单元格。这将使您获得最大的速度提升;使用mata代替-putexcel-会有所帮助,但只会提供二阶改进。即使在mata中,也要花很长时间才能分别写入数千个单元格。