[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

st: RE: if and if

From   "Nick Cox" <>
To   <>
Subject   st: RE: if and if
Date   Thu, 13 Nov 2008 14:31:33 -0000

This business of the two -if-s has confused many people. 

(Incidentally, I think -cond()- is a red herring as far as this question
is concerned. It is without doubt very useful, but it has no bearing on
the matter.) 

But what Ashim wants is, I think, not "in between" at all. He wants what
he calls Type 2 -- the -if- command -- to do the same as what he calls
Type 1 -- the -if- qualifier -- when both are based on tests on

However, it doesn't, and no amount of hoping, wishing, pushing or
shoving will make it so -- apart from one borderline exception. 

His query raises the question of why Stata has the two constructs if
they are really identical. But they aren't. 

It often happens that people used to some construct in other languages
would like to see Stata behave that way, and vice versa, but that's the
way it is. If you go to users' meetings (e.g. today and tomorrow in San
Francisco), you can confront the developers and say "Why is Stata
designed like that?". Sometimes there is a compelling argument against
one syntax and for another; sometimes the answer is "We had to make a
choice, and we just liked that syntax". But no syntax can be based on
users knowing that they mean one thing in one context and one thing in
another. All syntaxes have to be based on the language implementation
having only one interpretation of what is meant. 

I have got to say, however, that the Stata documentation is not 100%
innocent here. If you look at -help ifcmd- it gives among other details 

Typical use:  Example 3

    program ...
            if x==1      local word "one"
            else if x==2 local word "two"
            else if x==3 local word "three"
            else if x==4 local word "four"
            else         local word "big"

But this example is _only_ good programming style if -x- is a scalar.
(Arguably not even then, as a temporary name would be preferable.) And
that is not explained, or (to me) self-evident. 

Also, the fact that (again, for a variable x) 

if x == 1 ...

will be taken as 

if x[1] == 1 ...

is not explained in the help, although it is in [P] -if- and the FAQ
cited earlier in this thread. I think several people would find out
about this matter earlier and easier if the point were made in the help.

The borderline exception is thus that for a variable x 

if x == 1 ... 

is exactly equivalent to 

... if x == 1 

if and only if you have a single-observation dataset. 

There are languages that support something like 

if x == 1 ...

as equivalent to 

... if x == 1  

-- doesn't SAS support something similar -- but that is in a context
that implies a loop over observations. Stata's way of supporting loops
over observations (think of the ways that -generate- and -replace- work)
is more usually implicit. 

As Ashim pointed out, Stata offers a concise alternative to  

replace j=2 if k==2
replace m=2 if k==2
replace n=2 if k==2

It is 

foreach v of var j m n { 
	replace `v' = 2 if k == 2 

(Ashim's own code here is illegal, by virtue of his omitting "var".)

Alternatively, you can go 

foreach v in j m n { 

Short of Stata re-inventing itself as an ultra-terse language like APL
or J either seems to me about as concise as anyone might want. I really
don't understand why Ashim wants a "better way". What could be better,
or how is this lacking? 


Ashim Kapoor

I realize that there are 2 kinds if's in Stata.

Type 1 : would be something like replace j = 2 if k==2
here the replace in j would happen ONLY in the corresponding
observation of k. THIS IS WHAT I WANT.

Type 2 : the programming if something like

local j

if `j'==2 {

do something.



I guess I want to do something which is in between the above 2.

I want to say the following : --

replace j=2 if k==2
replace m=2 if k==2
replace n=2 if k==2

in ONE shot.

so I try : -
************************************** Block A
if k==2 {
replace j=2
replace m=2
replace n=2
This does not work. Because k==2 would mean k==2 in ALL observations.
While I mean to say make j / m / n = 2 in those observations where k
is 2.

How do I do this in a quick manner in Block A  ?

I understand that I can always do :-

foreach var of   j m n {
replace `var'=2 if k==2

But is there a better way ?

The reason I want this is the following  : -

I want

if k==2 {
replace j=1
replace m=5
replace n=89

so the above method fails as I do not have the SAME value 2 to be put
in each of j / m /n.

Any slick way of doing this ?

*   For searches and help try:

© Copyright 1996–2024 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index