Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Stata locals & loops using if condition

    Hi,

    I'm having a problem writing the correct loop code using an if condition.
    I'm using Stata 14.1 for Windows.

    I have set locals for each drug name & a local combining all the drug names. I have then generated a new variable for each of the drugs as follows:

    local drug1 `" possible string names for drug "'
    local drug2 `" possible string names for drug "'
    local drug3 `" possible string names for drug "'
    local alldrugs "drug1 drug2 drug3"

    foreach var of local alldrugs {
    gen `var'=.
    }

    I now want to replace the value of each new variable (drug1-drug3) with 1 if another variable (comdescription) contains the specific strings contained in the locals drug1-drug3 (i.e. replace the value of drug1 with 1 if comdescription matches any string held in the local drug1 and replace drug2=1 if string in comdescription matches any in drug2 local, etc.).

    So far I have written the following code, but it is not correct & I am unsure about how to write the if condition. I want the if statement to say "if the name of the variable equals the name of the local".

    foreach local of local alldrugs {
    foreach varname of local `local' {
    foreach x of local `local' {
    if `varname'[1]==`local'[1] { // if condition not correct (if the name of the variable equals the name of the local
    replace `varname'=1 if strmatch(lower(comdescription),"*`x'*")
    }
    }
    }
    }

    After a number of real changes have been made, the error I get is that one of my strings held in drug1 is not found.

    I could do this individually without the loops but I would like to learn how to use loops effectively & would really appreciate any advice on this matter.

    Thank you for your time.

    Best wishes,
    Bryony

  • #2
    Welcome to Statalist, Bryony.

    Here is some sample code that may start you in a useful direction.
    Code:
    local drug1 `" ibuprofen nuprin "'
    local drug2 `" advil acetominaphen "'
    local drug3 `" aspirin bayer "'
    local alldrugs "drug1 drug2 drug3"
    
    clear
    input str20 comd
    nuprin
    bayer
    advil
    ibuprofen
    ginseng
    end
    
    foreach drug of local alldrugs {
        gen `drug' = 0
    }
    
    foreach drug of local alldrugs {
        foreach name of local `drug' { 
            replace `drug' = 1 if comd=="`name'"
        }
    }
    Code:
    . list, clean
    
                comd   drug1   drug2   drug3  
      1.      nuprin       1       0       0  
      2.       bayer       0       0       1  
      3.       advil       0       1       0  
      4.   ibuprofen       1       0       0  
      5.     ginseng       0       0       0

    Comment


    • #3
      Hi, I have a similar problem with my code. I don´t understand what I´m doing wrong. I had an invalid syntax but I´m not sure what it is. I´m using STATA 16.

      Somebody can help me please?

      egen p402mean = rowmean(p4022012 p4022013 p4022014 p4022015 p4022016 p4022017)

      forvalues 2012(1)2017 {
      cap drop p402mean`i' p402_maxyear_`i'
      egen p402mean`i'= mean(p402mean`i')
      g p402_maxyear_`i'=1 if p402`i'>p402mean`i'
      replace p402_maxyear_`i'=0 if p402`i'<p402mean`i'
      replace p402_maxyear_`i'=. if p402`i'==.
      }


      Comment


      • #4
        The error is right at the top of your loop: -forvalues 2012(1)2017{- is the syntax error. Based on your frequent use of `i' inside the loop, I'm guessing what you meant is -forvalues i = 2012(1)2017 {-.

        However, when you fix that you encounter another error: -egen p402mean`i' = mean(p402mean`i')- cannot work because p402mean`i' has been -drop-ped in the immediately preceding command. (And if it weren't dropped, you'd still have an error because then you would be attempting to -egen- a variable that already exists. Since I don't know what you're actually trying to do with this code, I can't suggest a correction.

        If you can describe what the code is intended to calculate, I might be able to correct your code. Or, actually, it is most likely that no loop is even required and that the correct approach is to first -reshape- the data to long layout and then do something extremely simple after that. But, I'm just speculating now.

        Comment


        • #5
          Dears,
          I have the following probem.
          I want to run a regression for each local "activity1" and "activity2". The first regression on "activity1" should be conditioned on the first dummy from the local conditions ( cleaning_loundery); the regression on the second "activity2" should be conditioned on the second dummy (food_preparation). My current code is the following.

          local activity1 "age age2 female married"
          local activity2 "age age2 female married no_kids kids_less_six kids_more_six"
          local conditions "cleaning_loundery food_preparation"

          forvalues i = 1/2 {
          local act `activity`i''
          foreach y in `conditions' {
          reg schappy `act' if `y'==1, robust
          }
          }

          Clearly this code conditions with `y'==1 on both activities, which is not what I want to do.
          How could I solve this?
          Thank you in advance,
          Rezart

          Comment


          • #6
            Hi Rezart,

            you just need a function that extracts your dummy-names from your local "conditions". That is quite simple and can be done as follows:
            Code:
            local activity1 "age age2 female married"
            local activity2 "age age2 female married no_kids kids_less_six kids_more_six"
            local conditions cleaning_loundery food_preparation
            
            forvalues i = 1/2 {
            local act `activity`i''
            local cond `:word `i' of `conditions''
            reg schappy `act' if `cond'==1, robust
            }
            All the best,
            Benno

            Comment


            • #7
              Thank you so much Benno. It works perfectly.
              Regards.

              Comment


              • #8
                Benno Schoenberger answered your question nicely, but another take is that casting this problem as a loop is just unnecessary complication.

                You want two rather different regressions. Other than a robust option I think they are

                Code:
                regress schappy age age2 female married if cleaning_loundery == 1 
                
                regress schappy age age2 female married no_kids kids_less six_kids kids_more_six if food_preparation == 1
                Shorter code, simpler code, easier for everyone to follow, maintain and correct. Speaking for myself, I struggle mightily to understand your code without rewriting it.

                As a more pedantic detail, anyone reviewing or assessing your work will likely not care much about this, but loundery may be a typo for laundry.



                Comment


                • #9
                  Originally posted by Nick Cox View Post
                  Benno Schoenberger answered your question nicely, but another take is that casting this problem as a loop is just unnecessary complication.

                  You want two rather different regressions. Other than a robust option I think they are

                  Code:
                  regress schappy age age2 female married if cleaning_loundery == 1
                  
                  regress schappy age age2 female married no_kids kids_less six_kids kids_more_six if food_preparation == 1
                  Shorter code, simpler code, easier for everyone to follow, maintain and correct. Speaking for myself, I struggle mightily to understand your code without rewriting it.

                  As a more pedantic detail, anyone reviewing or assessing your work will likely not care much about this, but loundery may be a typo for laundry.


                  Hi Nick,

                  thank you for your reply. I presented here a simplified querry just to understand the command. My real problem concerned running multiple locals over many conditions. That's why I needed the loop.

                  Best,

                  Rezart

                  Comment


                  • #10
                    Dear Statalist users,

                    I have the following problem. I want to generate a new variable happy_`var' starting for values of the following variables:

                    local act1 "age female act_20101 act_20102"
                    local act2 "age female act_20201 act_20202 "

                    local coeff1 "clean_lound_age clean_lound_female clean_lound_act_20101 clean_lound_act_20102 "
                    local coeff2 "food_prep_age food_prep_female food_prep_act_20201 food_prep_act_20202"

                    local constant "clean_lound_const food_prep_const"

                    The code is the following:

                    forvalues i = 1/2 {
                    local act `act`i''
                    local coeff `coeff`i''
                    local const `:word `i' of `constant''
                    foreach var of varlist act_20101-act_20202 {
                    gen happy_`var'=`const' + total(`act'*`coeff') if `var'==1
                    }
                    }

                    In practical terms, I want to create a variable happy_`var' that is a sum of a constant (local constant) and the summation of variables values (local act) X by the coefficients of these variables (local coeff).

                    Any idea why this is not working? I'm attaching a sample code below.
                    Thank you in advance.
                    Rezart

                    Code:
                    * Example generated by -dataex-. To install: ssc install dataex
                    clear
                    input int age female act_20101 act_20102 act_20201 act_20202 clean_lound_age    clean_lound_female    food_prep_age    food_prep_female    clean_lound_const    food_prep_const)
                    59 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    80 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    80 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    16 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    80 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    57 0 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    75 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    58 1 1 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    54 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    48 0 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    80 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    47 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    62 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    66 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    30 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    48 0 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    17 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    30 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    30 1 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    50 0 0 0 0 0 -.008928726 .21669567 .00190265 .20030977 3.830127 3.490634
                    
                    end

                    Comment


                    • #11
                      total() is a function that can only be used in egen. You need more code to calculate the total you want.

                      Comment


                      • #12
                        Dear Nick,

                        I know that I could write the product variable by variable (instead of a command similar to total), but it would be very time consuming. Is there a way to do it within the loop?
                        Thank you in advance,

                        Rezart

                        Comment


                        • #13
                          You can and should write it in the loop. Sorry, right now I don't have the time and inclination to suggest code.

                          Comment


                          • #14
                            Dear Nick,

                            thank you anyway for the suggestion.

                            R

                            Comment


                            • #15
                              Hello Rezart,
                              this looks unnecessarily complicated to me. Did you calculate these "constants" and "coefficients" via some statistical model? Then you should use these values ​​directly for the calculation or store them in locals but not put them into variables that are constant for all observations (at least in your data example). For example, take a look at the following code:
                              Code:
                              sum age
                              return list
                              You can use all of these calculated values ​​directly for calculation. However, if you use other functions in between that also store results in r(), you should store the values ​​directly in locals for further use, for example like this.
                              Code:
                              local age_mean `r(mean)'
                              The way you wrote your loops can't work at all because you're trying to multiply a variable list with another variable list within the total function. If you simply insert what you previously defined into your locals, you get:
                              Code:
                              forvalues i = 1/2 {
                                  local act `act`i''
                                  --> local act age female act_20101 act_20102
                                  local coeff `coeff`i''
                                  --> local coeff clean_lound_age clean_lound_female clean_lound_act_20101 clean_lound_act_20102
                                  local const `:word `i' of `constant''
                                  --> local const clean_lound_const
                                  foreach var of varlist act_20101-act_20202 {
                                      egen happy_`var'=`const' + total(`act'*`coeff') if `var'==1
                                      --> egen happy_act_20101 = clean_lound_const + total(age female act_20101 act_20102 * clean_lound_age clean_lound_female clean_lound_act_20101 clean_lound_act_20102) if act_20101 ==1
                                  }
                              }
                              In addition, in step i =2 your previously generated variables happy_`var' cannot be generated again because they will already exist. Based on this unfortunately incorrect code, It is hard to imagine which variables you actually want to calculate and how.
                              It would probably be easiest if you wrote down the calculation of the 4 (or 8?) variables completely, then we could also help you with the locals and loops you need.

                              Comment

                              Working...
                              X