s_baldur
s_baldur

Reputation: 33498

Translating an R for loop into Stata

I have this simple problem to solve, that I need to solve using Stata. I am much more familiar with R, so I started by solving there to make sure I understand the problem and then wanted to translate to Stata.

The R Code for a similar problem

# Generate dummy data
n  <- 30L
df <- data.frame(id = seq_len(n))
set.seed(10L)
question <- c("qa", "qb", "qc")
for (q in question) {
  for (a in 1L:6L) {
    df[, paste(q, a, sep = "_")] <- sample(c(0L:10L, NA),
                                           size = n,
                                           replace = TRUE)
  }
}

# Now based on certain "activities" generate new variables
activity <- c(1, 4, 5, 6)

for (i in activity) {
  # If answer to question c for that activity is equal to 3
  # then value of the new variable is a multiple of the other two
  vara <- paste0("qa_", i)
  varb <- paste0("qb_", i)
  varc <- paste0("qc_", i)
  varn <- paste0("new", i)
  df[, varn] <- as.numeric(rep(NA, times = n))
  for (j in seq_len(n)) {
    if (is.na(df[j, varc])) {
      # Do nothing
    } else if (df[j, varc] == 3) {
      df[j, varn] <- df[j, vara] * df[j, varb]
    }
  }
}

What I've tested (played around with) in Stata

numlist "1 4 5 6"
global act `r(numlist)'
gen rows = _n

foreach i of global act {
   di "qa_" + `i'
   di "qb_" + `i'
   di "qc_" + `i'
   foreach j in rows {
     di `j'
   }
}

Having hard time finding the next steps.

Upvotes: 0

Views: 369

Answers (1)

Marco Sandri
Marco Sandri

Reputation: 24252

Here is the Stata code that generates columns new1, new4, new5, new6 as in your R code.

local numlist = "1 4 5 6"
local N = _N
foreach i in `numlist' {
   local vara = "qa_" + "`i'"
   local varb = "qb_" + "`i'"
   local varc = "qc_" + "`i'"
   local varn = "new" + "`i'"
   qui gen `varn'=.
   foreach j of numlist 1/`N' {
     if (`varc'[`j']==3) {
        qui replace `varn'=`vara'*`varb' in `j'
     }
   }
}
list new*, noobs sep(0)

  +---------------------------+
  | new1   new4   new5   new6 |
  |---------------------------|
  |    .      .      .      . |
  |    3      .      .      . |
  |    .      .      .      . |
  |   40      .      .      2 |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .     48      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      0      . |
  |    .      .      .      . |
  |    .      .      8      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    9      .     20      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  |    .      .      .      . |
  +---------------------------+

EDIT (Nick Cox): This would seem to reduce to

qui foreach i in 1 4 5 6 {
   gen new`i' = qa_`i' * qb_`i' if qc_`i' == 3 
}
list new*, noobs sep(0)

as the inner loop over observations is quite unnecessary and putting text into locals only to take it out again very quickly serves no point.

Upvotes: 2

Related Questions