Announcement

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

  • frget for multiple frames

    Hey everyone. I must confess that I am now a believer in frames. I've expressed confusion or skepticism about frames before, and now that I've used it for my own ends, I have discovered religion (well, I'm not religious, but on this issue). Below is a simplified dataset that estimates "leave one out" effects. How would I merge (frget) together many frames at once? In the end, all I need are the diff variables (the pointwise treatment effect) and cf (the counterfactual) in one frame, alongside the year and relative time period in question. is there a straightforward way to do this?
    Code:
    clear *
    
    loc trdate = 1989
    
    loc depvar cigsale
    
    u state year cigsale using "https://github.com/scunning1975/mixtape/blob/master/smoking.dta?raw=true", clear
    
    frame put state year cigsale, into(testframe)
    
    frame testframe: greshape wide cigsale, i(year) j(state)
    
    frame testframe: order cigsale3, a(year)
    
    
    cwf testframe
    
    loc labs2 4,5,8,9,19,20,21,32,34,37
    
    
    local donors: subinstr loc labs2 "," " ", all
    cls
    // grabs donors from existing macro
    
    qui ds // Gets a list of all variables
    
    loc temp: word 1 of `r(varlist)' // Time
    
    loc time: disp "`temp'"
    
    loc t: word 2 of `r(varlist)'
    
    loc treated_unit: disp "`t'" // T for treated
    
    loc a: word 3 of `r(varlist)'
    
    loc donor_one: disp "`a'" // First donor unit...
    
    local nwords :  word count `r(varlist)'
    
    loc b: word `nwords' of `r(varlist)'
    
    loc last_donor: disp "`b'" // Last donor...
    
    set tr off
    foreach j of loc donors {
    cwf testframe
    qui frame put `time'-`last_donor', into(effsans`j')
    frame effsans`j': drop `depvar'`j'
    
    cwf effsans`j'
    
    qui ds // Gets a list of all variables
    
    loc temp: word 1 of `r(varlist)' // Time
    
    loc time: disp "`temp'"
    
    loc t: word 2 of `r(varlist)'
    
    loc treated_unit: disp "`t'" // T for treated
    
    loc a: word 3 of `r(varlist)'
    
    loc donor_one: disp "`a'" // First donor unit...
    
    local nwords :  word count `r(varlist)'
    
    loc b: word `nwords' of `r(varlist)'
    
    loc last_donor: disp "`b'" // Last donor...
    
    qui reg `treated_unit' /// Treated Unit
        `donor_one'-`last_donor' /// Donor Pool
        if `time' < `trdate'
    cap drop cf_`j' // Makes our counterfactual*!!
    
    qui predict double cf_`j' // Here is our counterfactual
    
    //keep `time' `treated_unit' cf // We only need these
    
        if "`transform'" == "norm" { // standardizes it...
                
        qui replace cf_`j' = 1 if `time' ==`trdate'-1
        
        } // ends if
    
    lab var cf "Counterfactual California Without `j'"
    
    qui frame
    
    qui g relative = `time'- `trdate' // Generate an event-time variable
    
    qui g diff_`j' = `treated_unit'- cf // Difference between the cf and the observed outcomes
    //loc mainframe: di "`r(currentframe)'"
    
    qui frame put diff year cf, into(cf_`j')
    
    cwf cf_`j'
    
    frame default: loc clab: label (state) `j'
    di "`clab'"
    
    lab var cf_`j' "Synthetic California sans `clab'"
    }

  • #2
    I also do not see the point in frames, and I do not use them much. Your code is long, and somebody more versed in frames than me might come along...

    But once for fun I checked out frames, and this blog post was very useful:
    https://blog.stata.com/2019/09/06/fun-with-frames/
    you should check whether your question is not answered in this blog post.

    Comment


    • #3
      I think it will be more efficient here to collate the results using tempfile rather than frget. Too much work linking the frames. Either way, you have to loop.

      Code:
      clear *
      
      loc trdate = 1989
      
      loc depvar cigsale
      
      u state year cigsale using "https://github.com/scunning1975/mixtape/blob/master/smoking.dta?raw=true", clear
      
      frame put state year cigsale, into(testframe)
      
      frame testframe: greshape wide cigsale, i(year) j(state)
      
      frame testframe: order cigsale3, a(year)
      
      
      cwf testframe
      
      loc labs2 4,5,8,9,19,20,21,32,34,37
      
      
      local donors: subinstr loc labs2 "," " ", all
      cls
      // grabs donors from existing macro
      
      qui ds // Gets a list of all variables
      
      loc temp: word 1 of `r(varlist)' // Time
      
      loc time: disp "`temp'"
      
      loc t: word 2 of `r(varlist)'
      
      loc treated_unit: disp "`t'" // T for treated
      
      loc a: word 3 of `r(varlist)'
      
      loc donor_one: disp "`a'" // First donor unit...
      
      local nwords :  word count `r(varlist)'
      
      loc b: word `nwords' of `r(varlist)'
      
      loc last_donor: disp "`b'" // Last donor...
      
      set tr off
      foreach j of loc donors {
      cwf testframe
      qui frame put `time'-`last_donor', into(effsans`j')
      frame effsans`j': drop `depvar'`j'
      
      cwf effsans`j'
      
      qui ds // Gets a list of all variables
      
      loc temp: word 1 of `r(varlist)' // Time
      
      loc time: disp "`temp'"
      
      loc t: word 2 of `r(varlist)'
      
      loc treated_unit: disp "`t'" // T for treated
      
      loc a: word 3 of `r(varlist)'
      
      loc donor_one: disp "`a'" // First donor unit...
      
      local nwords :  word count `r(varlist)'
      
      loc b: word `nwords' of `r(varlist)'
      
      loc last_donor: disp "`b'" // Last donor...
      
      qui reg `treated_unit' /// Treated Unit
          `donor_one'-`last_donor' /// Donor Pool
          if `time' < `trdate'
      cap drop cf_`j' // Makes our counterfactual*!!
      
      qui predict double cf_`j' // Here is our counterfactual
      
      //keep `time' `treated_unit' cf // We only need these
      
          if "`transform'" == "norm" { // standardizes it...
                  
          qui replace cf_`j' = 1 if `time' ==`trdate'-1
          
          } // ends if
      
      lab var cf "Counterfactual California Without `j'"
      
      qui frame
      
      qui g relative = `time'- `trdate' // Generate an event-time variable
      
      qui g diff_`j' = `treated_unit'- cf // Difference between the cf and the observed outcomes
      //loc mainframe: di "`r(currentframe)'"
      
      qui frame put diff year cf, into(cf_`j')
      
      cwf cf_`j'
      
      frame default: loc clab: label (state) `j'
      di "`clab'"
      
      lab var cf_`j' "Synthetic California sans `clab'"
      }
      
      tempfile wanted
      foreach d of local donors{
          frame change effsans`d'
          keep year cf_`d' relative diff_`d'
          rename relative relative_`d'
          cap merge 1:1 year using `wanted', nogen
          save `wanted', replace
      }
      use `wanted', clear
      browse

      Comment


      • #4
        Just a couple of stray thoughts about when frames are useful. In principle, anything that can be done with frames can be done with tempfiles as well. I think there are a few situations where frames are, in my opinion, superior (not in order of importance):
        1. With large data sets, having everything in memory should make execution faster, though I don't know if this is actually the case.
        2. In a process where you need, in effect, to merge two data sets but the key variables have different names, the code is cleaner and more transparent with frames than with -rename-ing variables in tempfiles.
        3. In a process where you need, in effect, to merge two data sets repeatedly, but with different key variables each time, you can have all of these links active simultaneously with frames, but not with tempfiles. So again, the code becomes simpler, much simpler, in fact.
        4. In a process which is best performed on a subset of the data, and where the excluded observations actually "get in the way", the simplest solution is to -frame put- the subset into another frame, perform the process with simple code, and then link and bring back the results. While you could also do this with a tempfile, the necessary rigmarole of preserving, restoring, etc. make the code longer and less transparent than the analogous process with frames.

        Comment

        Working...
        X