问题
How can I edit every 2nd value of a variable?
My code is:
set obs 100
gen u = invnorm(uniform())
forvalues d = 1/50 {
gen u[2*d] = u[2*d] + 1
}
What's wrong with my code?
回答1:
The syntax for generate
doesn't allow anything except a storage type and variable name (and a label name, irrelevant here) after generate
and before =
. This is clearly indicated by the help file.
You don't need a loop here. If you want to work on observations 2, 4, ... then
gen new_u = u + 1 if mod(_n, 2) == 0
selects even observation numbers. To change an existing variable generate
is illegal, but you could go
replace u = u + 1 if mod(_n, 2) == 0
An abbreviation for
mod(_n, 2) == 0
is
!mod(_n, 2)
given that the modulus (strictly, remainder) on dividing integers by 2 can only be 1 or 0, so negating zeros (logical false) gives you ones (logical true).
P.S.
invnorm(uniform())
is an ancient way to call random normal deviates with mean 0 and variance 1. In modern Statas
rnormal()
will do it.
回答2:
A one-line version of your loop would be:
gen u = rnormal(!mod(_n,2),1)
The logic is that you start with draws from a standard normal distribution and want to add 1 to all even observations. Adding 1 means that the mean for the distribution is 1 instead of 0. The first argument of the rnormal()
function is the mean. So if we can feed that a 0 for all the odd observations and 1 for all the even observations, then we are done. As @NickCox noted in his answer such a function is !mod(_n,2)
Having said that, Nick's two line solution
gen u = rnormal()
replace u = u + 1 if mod(_n, 2) == 0
may be easier to read. That would be a very good reason for choosing Nick's solution.
来源:https://stackoverflow.com/questions/23783837/stata-elements-of-variable