1

This question has been edited to add sample data and clean-up (hopefully) some unnecessary steps per feedback.

I am starting with longitudinal data in wide format. I need to subset, reshape, and perform summary steps for multiple different chunks of data. I want to create macro variables with varlists needed for reshaping and other repetitive steps in wide and long format. The variables being reshaped follow a consistent naming pattern of (prefix)_(name)_#. There are also variables following the same pattern that do not need to be reshaped, and variables that are time-invariant and follow other naming conventions. To generate sample data:

set obs 1  
foreach t in 0 6 15 18 21 { 
foreach w in score postint postintc constime starttime { 
      gen p_`w'_`t' = 1 
    }
}
gen p_miles_0 = 1
gen p_hea_0 = 1
gen cons_age = 1

ds

I want to create two macro vars 1) wide_varlist for wide format data where the variables end in a number and 2) uniquestubs for long format data where the macro list contains just the stubs. I am having trouble using the macro list extended function "uniq" to generate #2 here. Here is my code so far. My full varlists are actually much longer.

Steps to create macro with wide format varlist:

/* create varlist for wide format data a time point 0,6,15,18,21 */
ds  p_score_* p_postint_* p_postintc_* p_constime_* p_starttime_*
di "`r(varlist)'"
global wide_varlist `r(varlist)'

Start steps to create macro with long format varlist:

/*copy in wide format varlist*/
global stubs "$wide_varlist"

/*remove # - this results in a macro with 5 dups of same stub*/
foreach mo of numlist 0,6,15,18,21{
    global stubs : subinstr global stubs "`mo'" "", all
}

/*keep unique stubs*/
global uniquestubs : list uniq stubs

Everything above works as I intend until global uniquestubs : list uniq stubs, which doesn't create the macro uniquestubs at all.

My situation seems similar to this this question but the same solution didn't work for me.

Any thoughts? Appreciate the help.

jrc
  • 35
  • 1
  • 7

1 Answers1

2

It's a bit difficult to follow what you are trying to do (a) without a reproducible example (b) because much of your code is just copying the same varlist to different places, which is a distraction.

We can fix (a) by creating a toy dataset:

clear 
set obs 1 
foreach t in 0 6 15 18 21 { 
    foreach w in score postint postintc constime starttime { 
        gen p_`w'_`t' = 1 
    }
}

ds
p_score_0     p_score_6     p_score_15    p_score_18    p_score_21
p_postint_0   p_postint_6   p_postint_15  p_postint_18  p_postint_21
p_postintc_0  p_postintc_6  p_postintc~5  p_postintc~8  p_postintc~1
p_constime_0  p_constime_6  p_constim~15  p_constim~18  p_constim~21
p_starttim~0  p_starttim~6  p_startti~15  p_startti~18  p_startti~21

Now the main difficulty seems to be that you want stubs for a reshape long. This code suffices for the toy dataset. There is no need to scan yet more variable names with the same information. If you don't have all variables for all time points, you may need more complicated code.

unab stubs:  p_*_0 
local stubs : subinstr local stubs "0" "", all 
di "`stubs'" 

p_score_ p_postint_ p_postintc_ p_constime_ p_starttime_

I don't understand the enthusiasm for globals here, but, programming taste aside, you can put the last result in a global quite easily.

Nick Cox
  • 35,529
  • 6
  • 31
  • 47
  • Thank you, Nick. I apologize for the difficult presentation and thanks for generating the sample data. Yes, I do want the stubs for `reshape long` and additional steps that run summary statistics later (hence the preference for globals). There are other variables in the data set that will get picked up by p_*_0 that I don't want in this stub list. Will the `uniq` extended function work for this example in any way (my redundant coding aside)? Just trying to understand this function and couldn't figure it out using the Stata manual or previous questions. – jrc Jun 12 '17 at 16:47
  • So, you need to revise what you feed to `unab` and/or some surgery afterwards to remove what you don't want. I can't suggest code as your signal is just that your real problem is more complicated than you said. Sorry, but I couldn't make sense of what you were trying to do with `uniq`. At this moment I lack the enthusiasm to suggest two solutions. – Nick Cox Jun 12 '17 at 17:33
  • Otherwise put, it's stalemate here. Understood that my code doesn't do precisely what you want, but unless and until you explain what's missing then there seems no point in guessing wildly at how to modify this solution, or to suggest another one, which would have the same limitation to the same example variable names. – Nick Cox Jun 12 '17 at 20:43
  • I edited my original question, hopefully for the better. Your initial answer works with some modifications. My problem is resolved, but I'm still curious about using the `uniq` function because it might be useful elsewhere, so maybe others will respond to that. Thanks for your time. – jrc Jun 13 '17 at 21:25
  • Your problem is documented at `help macrolists`. If you're feeding a global macro to `list uniq` you must spell out that it is a global with that keyword. Thus you need `: list uniq global stubs`. The approach via `uniq` still seems very roundabout to me. You're knowingly creating a list too large and then have to slim it down again. BTW, I have often created wide and long versions of data files and never felt the need to use globals in so doing. – Nick Cox Jun 13 '17 at 23:45
  • Note that although `unab stubs: p_*_0` would catch too much in your revised example, `unab stubs: p_*_6` would be fine. – Nick Cox Jun 14 '17 at 06:32
  • Thanks for the multiple workable solutions. Globals vs locals is a different/bigger question, so I won't dig much deeper here. I've gotten hung up on locals not working for the way I code (which I'm certain could be improved, but it works until I have time to learn a better way). I understand it's probably overkill and has pitfalls. – jrc Jun 15 '17 at 14:39