Loop over a do file with regression model in Stata - loops

I am estimating several regressions in Stata with the same functional form. I'd like to perform my estimations by looping over a .do file that contains the "program" for my regression. The (simplified) code I have attempted is as follows:
local vars waz haz whz cough fever diar
foreach depvar of local vars {
forvalues i = 10(5)15 {
do "Regression.do"
}
}
Where "Regression.do" is this code:
reg `depvar' distance_`i'
est store `depvar'_`i'
Stata returns an error message: "Error: last estimates not found." How can I amend my code so that I can execute the .do file in a loop?

Simplifying your code as suggested by #Nick Cox is best, however, to answer your question the solution is below:
main do-file
local vars waz haz whz cough fever diar
foreach depvar of local vars {
forvalues i = 10(5)15 {
do "Regression.do" "`i'"
}
}
regression.do
reg `depvar' distance_`1'
est store `depvar'_`1'

The do-file is hardly needed in this example. Using its contents directly avoids the problem that local macros are ... local ... meaning only visible within the same program space.
foreach depvar in waz haz whz cough fever diar {
foreach num in 10 15 {
reg `depvar' distance_`num'
est store `depvar'_`num'
}
}
is one way to simplify your code. although that is partly a matter of taste.
See also https://journals.sagepub.com/doi/pdf/10.1177/1536867X20931028 for more on what bit you.
I see a lot of Stata code which puts content into a local macro only to take it out again just once and immediately. This is like "I have a pen. I put it in a box. I take it out of the box. I now have my pen again." Sometimes the box (meaning, local macro) is a good idea; but other times there is no gain to writing the code that way.
You do flag that you have fuller code, which is fair enough, and at some point having a do-file and passing arguments to it may appear to be better style.
As partly explained in the answer of #24thDan, you can pass arguments to a do-file, which is how a local macro's contents can become visible to and within a do-file.
You can rewrite your do-file this way
* regression.do
args depvar num
regress `depvar' distance_`num'
est store `depvar'_`num'
and within your loops call it with
do regression.do `depvar' `num'
As in the other answer, you can within the do-file refer to the first, second, ... arguments numbering them as 1, 2, and so on, but I recommend the use of args to map those local macros to other macros with intelligible names.

Related

Package-qualified names. Differences (if any) between Package::<&var> vs &Package::var?

Reading through https://docs.perl6.org/language/packages#Package-qualified_names it outlines qualifying package variables with this syntax:
Foo::Bar::<$quux>; #..as an alternative to Foo::Bar::quux;
For reference the package structure used as the example in the document is:
class Foo {
sub zape () { say "zipi" }
class Bar {
method baz () { return 'Þor is mighty' }
our &zape = { "zipi" }; #this is the variable I want to resolve
our $quux = 42;
}
}
The same page states this style of qualification doesn't work to access &zape in the Foo::Bar package listed above:
(This does not work with the &zape variable)
Yet, if I try:
Foo::Bar::<&zape>; # instead of &Foo::Bar::zape;
it is resolves just fine.
Have I misinterpreted the document or completely missed the point being made? What would be the logic behind it 'not working' with code reference variables vs a scalar for example?
I'm not aware of differences, but Foo::Bar::<&zape> can also be modified to use {} instead of <>, which then can be used with something other than literals, like this:
my $name = '&zape';
Foo::Bar::{$name}()
or
my $name = 'zape';
&Foo::Bar::{$name}()
JJ and Moritz have provided useful answers.
This nanswer is a whole nother ball of wax. I've written and discarded several nanswers to your question over the last few days. None have been very useful. I'm not sure this is either but I've decided I've finally got a first version of something worth publishing, regardless of its current usefulness.
In this first installment my nanswer is just a series of observations and questions. I also hope to add an explanation of my observations based on what I glean from spelunking the compiler's code to understand what we see. (For now I've just written up the start of that process as the second half of this nanswer.)
Differences (if any) between Package::<&var> vs &Package::var?
They're fundamentally different syntax. They're not fully interchangeable in where you can write them. They result in different evaluations. Their result can be different things.
Let's step thru lots of variations drawing out the differences.
say Package::<&var>; # compile-time error: Undeclared name: Package
So, forget the ::<...> bit for a moment. P6 is looking at that Package bit and demanding that it be an already declared name. That seems simple enough.
say &Package::var; # (Any)
Quite a difference! For some reason, for this second syntax, P6 has no problem with those two arbitrary names (Package and var) not having been declared. Who knows what it's doing with the &. And why is it (Any) and not (Callable) or Nil?
Let's try declaring these things. First:
my Package::<&var> = { 42 } # compile-time error: Type 'Package' is not declared
OK. But if we declare Package things don't really improve:
package Package {}
my Package::<&var> = { 42 } # compile-time error: Malformed my
OK, start with a clean slate again, without the package declaration. What about the other syntax?:
my &Package::var = { 42 }
Yay. P6 accepts this code. Now, for the next few lines we'll assume the declaration above. What about:
say &Package::var(); # 42
\o/ So can we use the other syntax?:
say Package::<&var>(); # compile-time error: Undeclared name: Package
Nope. It seems like the my didn't declare a Package with a &var in it. Maybe it declared a &Package::var, where the :: just happens to be part of the name but isn't about packages? P6 supports a bunch of "pseudo" packages. One of them is LEXICAL:
say LEXICAL::; # PseudoStash.new(... &Package::var => (Callable) ...
Bingo. Or is it?
say LEXICAL::<&Package::var>(); # Cannot invoke this object
# (REPR: Uninstantiable; Callable)
What happened to our { 42 }?
Hmm. Let's start from a clean slate and create &Package::var in a completely different way:
package Package { our sub var { 99 } }
say &Package::var(); # 99
say Package::<&var>(); # 99
Wow. Now, assuming those lines above and trying to add more:
my Package::<&var> = { 42 } # Compile-time error: Malformed my
That was to be expected given our previous attempt above. What about:
my &Package::var = { 42 } # Cannot modify an immutable Sub (&var)
Is it all making sense now? ;)
Spelunking the compiler code, checking the grammar
1 I spent a long time trying to work out what the deal really is before looking at the source code of the Rakudo compiler. This is a footnote covering my initial compiler spelunking. I hope to continue it tomorrow and turn this nanswer into an answer this weekend.
The good news is it's just P6 code -- most of Rakudo is written in P6.
The bad news is knowing where to look. You might see the doc directory and then the compiler overview. But then you'll notice the overview doc has barely been touched since 2010! Don't bother. Perhaps Andrew Shitov's "internals" posts will help orient you? Moving on...
In this case what I am interested in is understanding the precise nature of the Package::<&var> and &Package::var forms of syntax. When I type "syntax" into GH's repo search field the second file listed is the Perl 6 Grammar. Bingo.
Now comes the ugly news. The Perl 6 Grammar file is 6K LOC and looks super intimidating. But I find it all makes sense when I keep my cool.
Next, I'm wondering what to search for on the page. :: nets 600+ matches. Hmm. ::< is just 1, but it is in an error message. But in what? In token morename. Looking at that I can see it's likely not relevant. But the '::' near the start of the token is just the ticket. Searching the page for '::' yields 10 matches. The first 4 (from the start of the file) are more error messages. The next two are in the above morename token. 4 matches left.
The next one appears a quarter way thru token term:sym<name>. A "name". .oO ( Undeclared name: Package So maybe this is relevant? )
Next, token typename. A "typename". .oO ( Type 'Package' is not declared So maybe this is relevant too? )
token methodop. Definitely not relevant.
Finally token infix:sym<?? !!>. Nope.
There are no differences between Package::<&var> and &Package::var.
package Foo { our $var = "Bar" };
say $Foo::var === Foo::<$var>; # OUTPUT: «True␤»
Ditto for subs (of course):
package Foo { our &zape = { "Bar" } };
say &Foo::zape === Foo::<&zape>;# OUTPUT: «True␤»
What the documentation (somewhat confusingly) is trying to say is that package-scope variables can only be accessed if declared using our. There are two zapes, one of them has got lexical scope (subs get lexical scope by default), so you can't access that one. I have raised this issue in the doc repo and will try to fix it as soon as possible.

loop over variables and years

I am trying to generate variables in the form varyear based on a list of original variables with random variable names. For example, based on the first variable E4252, I'll get a new variable called var2013; then var2011,
var2009, var2007 and so on to var1999.
Here is what I wrote, but didn't work:
local myvar "E4252 E5219 E4693 E4102 E2803 E2046 E1462 E1079"
local i = 2015
foreach x of myvar {
local i = `i' - 2
gen var`i' = `x'
}
You need to tell Stata that myvar is a local in your loop:
local myvar "E4252 E5219 E4693 E4102 E2803 E2046 E1462 E1079"
local i = 2015
foreach x of local myvar {
local i = `i' - 2
gen var`i' = `x'
}
Alternatively, you can refer the contents of the local directly:
foreach x in `myvar' {
...
}
Some alternatives to #Dimitriy's good answer.
For a short list of names like this, you can be direct and avoid a local macro. It's just an extra level of indirection.
Why generate at all? It sounds as if you are adopting a better set of variable names, so rename saves you having the same information repeated in two sets of variables.
I'd start with the first year used, i.e. 2013 not 2015.
local i = 2013
foreach x in E4252 E5219 E4693 E4102 E2803 E2046 E1462 E1079 {
rename `x' var`i'
local i = `i' - 2
}
You could just use rename all at once.
rename (E4252 E5219 E4693 E4102 E2803 E2046 E1462 E1079) (var2013 var2011 var2009 var2007 var2005 var2003 var2001 var1999)
There is a simple trade-off here.
The last code example is simple and direct and it's easy to see at a glance what has been done.
But if you don't play with loops, you never learn good technique.
I wouldn't want to type out any (much) longer list of names, but people are going to have different thresholds here. Also, you may have other problems of the same type, which makes mastering loop technique more important.

Locating a dynamic string in a text file

Problem:
Hello, I have been struggling recently in my programming endeavours. I have managed to receive the output below from Google Speech to Text, but I cannot figure out how draw data from this block.
Excerpt 1:
[VoiceMain]: Successfully initialized
{"result":[]}
{"result":[{"alternative":[{"transcript":"hello","confidence":0.46152416},{"transcript":"how low"},{"transcript":"how lo"},{"transcript":"how long"},{"transcript":"Polo"}],"final":true}],"result_index":0}
[VoiceMain]: Successfully initialized
{"result":[]}
{"result":[{"alternative":[{"transcript":"hello"},{"transcript":"how long"},{"transcript":"how low"},{"transcript":"howlong"}],"final":true}],"result_index":0}
Objective:
My goal is to extract the string "hello" (without the quotation marks) from the first transcript of each block and set it equal to a variable. The problem arises when I do not know what the phrase will be. Instead of "hello", the phrase may be a string of any length. Even if it is a different string, I would still like to set it to the same variable to which the phrase "hello" would have been set to.
Furthermore, I would like to extract the number after the word "confidence". In this case, it is 0.46152416. Data type does not matter for the confidence variable. The confidence variable appears to be more difficult to extract from the blocks because it may or may not be present. If it is not present, it must be ignored. If it is present however, it must be detected and stored as a variable.
Also please note that this text block is stored within a file named "CurlOutput.txt".
All help or advice related to solving this problem is greatly appreciated.
You could do this with regex, but then I am assuming you will want to use this as a dict later in your code. So here is a python approach to building this result as a dictionary.
import json
with open('CurlOutput.txt') as f:
lines = f.read().splitlines()
flag = '{"result":[]} '
for line in lines: # Loop through each lin in file
if flag in line: # check if this is a line with data on it
results = json.loads(line.replace(flag, ''))['result'] # Load data as a dict
# If you just want to change first index of alternative
# results[0]['alternative'][0]['transcript'] = 'myNewString'
# If you want to check all alternative for confidence and transcript
for result in results[0]['alternative']: # Loop over each alternative
transcript = result['transcript']
confidence = None
if 'confidence' in result:
confidence = result['confidence']
# now do whatever you want with confidence and transcript.

for each (root of variable) in SPSS

I'm new in SPSS program but I've tried to search a solution to my problem. The idea is find a way to loop through some variable names (or I think so). I want to create the variables P216_XX, P217_XX, T211_XX and OCUPAC_XX, with other variables like some inputs (P216_13, P216_12, P216_11, P216_10, P217_13, P217_12, P217_11, P217_10, T211_13, T211_12, T211_11, T211_10, OCUPAC_13, OCUPAC_12, OCUPAC_11, OCUPAC_10 and IIIDDDEEE).
I'm following the next tedious instruction:
******TEDIOUS INSTRUCTION:
*****P216_XX.
IF (IIIDDDEEE=1) P216_XX=P216_13.
EXECUTE.
IF (IIIDDDEEE=2) P216_XX=P216_12.
EXECUTE.
IF (IIIDDDEEE=3) P216_XX=P216_11.
EXECUTE.
IF (IIIDDDEEE=4) P216_XX=P216_10.
EXECUTE.
*****P217_XX.
IF (IIIDDDEEE=1) P217_XX=P217_13.
EXECUTE.
IF (IIIDDDEEE=2) P217_XX=P217_12.
EXECUTE.
IF (IIIDDDEEE=3) P217_XX=P217_11.
EXECUTE.
IF (IIIDDDEEE=4) P217_XX=P217_10.
EXECUTE.
*****T211_XX.
IF (IIIDDDEEE=1) T211_XX=T211_13.
EXECUTE.
IF (IIIDDDEEE=2) T211_XX=T211_12.
EXECUTE.
IF (IIIDDDEEE=3) T211_XX=T211_11.
EXECUTE.
IF (IIIDDDEEE=4) T211_XX=T211_10.
EXECUTE.
*****OCUPAC_XX.
IF (IIIDDDEEE=1) OCUPAC_XX=OCUPAC_13.
EXECUTE.
IF (IIIDDDEEE=2) OCUPAC_XX=OCUPAC_12.
EXECUTE.
IF (IIIDDDEEE=3) OCUPAC_XX=OCUPAC_11.
EXECUTE.
IF (IIIDDDEEE=4) OCUPAC_XX=OCUPAC_10.
EXECUTE.
In stata, the form would reduce the previous syntax with something like that:
foreach x in P216 P217 T211 OCUPAC {
replace `x'_XX=`x'_13 if IIIDDDEEE==1
replace `x'_XX=`x'_12 if IIIDDDEEE==2
replace `x'_XX=`x'_11 if IIIDDDEEE==3
replace `x'_XX=`x'_10 if IIIDDDEEE==4
}
*
In SPSS, I proved with vector, but SPSS don't accept me root in the vector, only variables. I don't know how to continue and I haven't found something similar yet
Is possible found a solution with native SPSS language? (I forgot to comment that in my work, the "administrator" doesn't allow us to install other programs like Python). What would be a possible solution?
There are a quite a lot of ways you can simplify this code, look up:
DEFINE/ENDDEFINE, SPSS's macro language.
DO IF
DO REPEAT
You need to be familiar with each and know what your end goal is to assess which option is best for you.

Alternative to putting an include inside a While loop

I have a chunk of PHP code that I'd like to include on a number of different pages but be able to update in one location (hence my use of an include file). However, the chunk of code needs to appear inside a while loop -- specifically inside a while loop that is echoing out MySQL rows.
However, there are roughly 200 rows in the MySQL query I'm echoing, so having an include in the loop really slows things down. I've tried making what's in the include file a function, like shown below, then including once at the top of the page and referencing the function inside the loop, but it it doesn't seem to work (I just don't get any data in the variables I'm setting, etc.)
How does one put a chunk of code inside a loop without using include?
Thanks very much.
function CYCalc()
{
// If the company's current fiscal quarter
// is equal to the current calendar quarter,
// use the company's fiscal years as calendar years
if ($UniverseResult[CurQ] == "Q1" && $UniverseResult[CurYear] == "2012") {
$C2011Sales = number_format($UniverseResult[SalesYear2]/1000000,1);
$C2012Sales = number_format($UniverseResult[SalesYear3]/1000000,1);
$C2011EPS = $UniverseResult[EPSYear2];
$C2012EPS = $UniverseResult[EPSYear3];
}
}
Remember PHP's scoping rules. Variables defined in the global scope are not visible inside functions unless you explicitly declare them as global within the function:
<?php
$x = 7;
function y() {
echo $x; // undefined
}
function z() {
global $x;
echo $x; // 7
}
function a($x) {
echo $x; // 7
}
For your CYCalc() to work, you'd need to declare $UniverseResult global as per z() above, or pass it in as a parameter as per a() above.

Resources